2016-07-12 5 views
1

私は問題を抱えています。 ので、ここでの例です:C#いくつかのバックグラウンドワーカー同じメソッド

int threadnumber = 0; 
int retries[] = new int[8]; 

private XmlDocument GetXML(string ApiUrl, int threadnumber) 
     { 
      var mySourceDoc = new XmlDocument(); 
      try 
      { 
       var httpRequest = (HttpWebRequest)WebRequest.Create(ApiUrl); 
       httpRequest.Timeout = 50000; 
       if (cb_Proxy.Checked == true) 
       { 
        WebProxy germanserver = new WebProxy(); 
        Uri newUri = new Uri("http://" + txt_Proxy.Text); 
        germanserver.Address = newUri; 
        httpRequest.Proxy = germanserver; 
       } 
       var response = (HttpWebResponse)httpRequest.GetResponse(); 
       var receiveStream = response.GetResponseStream(); 
       receiveStream.ReadTimeout = 150000; 
       mySourceDoc.Load(receiveStream); 
       receiveStream.Close(); 
       retries[threadnumber-1] = 1; 
      } 
      catch (Exception ex) 
      { 
       //DialogResult MessBox = MessageBox.Show("Der Server ist nicht erreichbar oder es ist ein anderes Problem mit dem Server aufgetreten. Es wird automatisch 3 mal erneut versucht. Fehlermeldung anzeigen?", "Fehler", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); 
       //if (MessBox == DialogResult.Yes) MessageBox.Show(ex.Message); 
       retries[threadnumber - 1]++; 
       consoletext = "Fehler: " + ex.Message + "; Neuer Versuch " + retries[threadnumber - 1] + " von Url " + ApiUrl + Environment.NewLine; 
       if (threadnumber == 1) workingHelper1.ReportProgress(counterhelper[0]); 
       if (threadnumber == 2) workingHelper2.ReportProgress(counterhelper[1]); 
       if (threadnumber == 3) workingHelper3.ReportProgress(counterhelper[2]); 
       if (threadnumber == 4) workingHelper4.ReportProgress(counterhelper[3]); 
       if (threadnumber == 5) workingHelper5.ReportProgress(counterhelper[4]); 
       if (threadnumber == 6) workingHelper6.ReportProgress(counterhelper[5]); 
       if (threadnumber == 7) workingHelper7.ReportProgress(counterhelper[6]); 
       if (threadnumber == 8) workingHelper8.ReportProgress(counterhelper[7]); 
       Thread.Sleep(3000); 
      } 
      finally 
      { 
       if (retries[threadnumber - 1] > 1 && retries[threadnumber - 1] <= 3) GetXML(ApiUrl, threadnumber); 
       if (retries[threadnumber - 1] >= 4) retries[threadnumber] = 1; 
      } 
      return mySourceDoc; 
} 

backgroundworkersが生成されたURL文字列とthreadnumber 1-8でメソッドのgetXMLをコールします。 私の問題は、再試行が5以上になることがあることです。私はバックグラウンドの人たちが同じ変数に時々アクセスしてそれを数えると思いますか?

+1

TPLなどの代わりにバックグラウンドワーカーを使用する理由はありますか? – Petaflop

+0

これは良い質問です。私はbackgroundworkersとして別のオプションについて考えたことはありません。いくつかのバックグラウンド労働者が同じ方法で変数にアクセスした場合、 threadnumberは他のワーカーによって実行時にオーバーライドできますか? –

+0

スレッド間の再帰呼び出しは、何が起こっているかを理解するのにはあまり役に立ちません。あなたのメソッドを 'async'にし、他のメソッドからの結果を' await'して、必要な回数だけコールを再試行することができます。 – Petaflop

答えて

0

複数のスレッドが同じオブジェクトを同時に操作できるようにすることは、一般的にはお勧めできません。これは間違いなく、操作されたオブジェクトの状態で競合を引き起こすことになります。

共有変数(threadnumberおよびretries)にアクセスして操作する行にlockを使用することを検討してください。各ワーカースレッドがretries配列(すなわちthreadnumberthreadnumber - 1)から2つのエントリが必要ですので、あなたが呼び出すことができないことのように思える

  1. :ので

    はまた、あなたがメソッドを呼び出している方法を検討し

    GetXMLメソッドが連続してthreadnumberの値を持つ場合は、retries配列に競合が発生します。あるいは、これはあなたのコードでこの問題の原因となっているバグ(下に引用されています)です。

    if(retries [threadnumber-1]> = 4)retries [threadnumber] = 1;

  2. GetXMLメソッドを呼び出しているコードを検討し、それが複数の労働者に同じthreadnumberを割り当てていないことを確認してください。

+1

'threadnumber'は共有変数ではなくパラメータです。 retries'が同時にアクセスされる 'のに対し、それが問題である変数へのアクセスを共有している可能性がありませんように、それは常に、(私がコメントで述べた一つの場合、中を除く)' threadnumber-1 'にインデックスを付けています。 –

+0

しかし、私は問題がthreadnumber ...と思うgetxml(bla1、1)そして同時に次のワーカーgetxml(bla2,2)とメソッドでスレッドナンバーをオーバーライドできると思いますか? –

0

論理的な失敗と思われます。今私は各スレッドと実際の変数の内容をデバッグしました。だから、それはすべてOKと思われ、変数をオーバーライドすることはできません。

コードを編集したので、3回目の再試行後にメソッドが異常終了します。

private XmlDocument GetXML(string ApiUrl, int threadnumber) 
    { 
     object thislock = new object(); 
     lock (thislock) 
     { 
      var mySourceDoc = new XmlDocument(); 
      try 
      { 
       var httpRequest = (HttpWebRequest)WebRequest.Create(ApiUrl); 
       httpRequest.Timeout = 50000; 
       if (cb_Proxy.Checked == true) 
       { 
        WebProxy proxy = new WebProxy(); 
        Uri newUri = new Uri("http://" + txt_Proxy.Text); 
        proxy.Address = newUri; 
        httpRequest.Proxy = proxy; 
       } 
       var response = (HttpWebResponse)httpRequest.GetResponse(); 
       var receiveStream = response.GetResponseStream(); 
       receiveStream.ReadTimeout = 150000; 
       mySourceDoc.Load(receiveStream); 
       receiveStream.Close(); 
       retries[threadnumber - 1] = 1; 
      } 
      catch (Exception ex) 
      { 
       retries[threadnumber - 1]++; 
       if (retries[threadnumber - 1] == 4) 
       { 
        consoletext = "Endgültiger Abbruch von Url " + ApiUrl + Environment.NewLine; 
        writeLog("Worker: " + threadnumber + " Endgültiger Abbruch von Url " + ApiUrl); 
       } 
       else 
       { 
        consoletext = "Fehler: " + ex.Message + "; Neuer Versuch " + retries[threadnumber - 1] + " von Url " + ApiUrl + Environment.NewLine; 
        writeLog(ex.Message + "; Versuch: " + retries[threadnumber - 1] + " Thread: " + threadnumber + " URL: " + ApiUrl); 
       } 
       //DialogResult MessBox = MessageBox.Show("Der Server ist nicht erreichbar oder es ist ein anderes Problem mit dem Server aufgetreten. Es wird automatisch 3 mal erneut versucht. Fehlermeldung anzeigen?", "Fehler", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1); 
       //if (MessBox == DialogResult.Yes) MessageBox.Show(ex.Message); 

       if (threadnumber == 1) workingHelper1.ReportProgress(counterhelper[0]); 
       if (threadnumber == 2) workingHelper2.ReportProgress(counterhelper[1]); 
       if (threadnumber == 3) workingHelper3.ReportProgress(counterhelper[2]); 
       if (threadnumber == 4) workingHelper4.ReportProgress(counterhelper[3]); 
       if (threadnumber == 5) workingHelper5.ReportProgress(counterhelper[4]); 
       if (threadnumber == 6) workingHelper6.ReportProgress(counterhelper[5]); 
       if (threadnumber == 7) workingHelper7.ReportProgress(counterhelper[6]); 
       if (threadnumber == 8) workingHelper8.ReportProgress(counterhelper[7]); 
       Thread.Sleep(3000); 
      } 
      finally 
      { 
       if (retries[threadnumber - 1] > 1 && retries[threadnumber - 1] <= 3) GetXML(ApiUrl, threadnumber); 
       //if (retries[threadnumber - 1] >= 4) retries[threadnumber - 1] = 1; 
       else retries[threadnumber - 1] = 1; 
      } 
      return mySourceDoc; 
     } 
    } 
関連する問題