2016-07-12 4 views
1

나는 2-8 배경 작업자가 같은 방법으로 액세스 할 때 문제가 발생합니다. 그래서 여기 일례이다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; 
} 

생성 URL 문자열과의 ThreadNumber 1-8와 메소드를 호출은 GetXML backgroundworkers. 내 재시도가 5 이상이되는 경우가 있습니다. 그래서 나는 종종 같은 변수에 액세스하고 그것을 세는 백 선인들이라고 생각합니까?

+1

TPL 대신 또는 이와 유사한 배경 작업자를 사용해야하는 이유가 있습니까? – Petaflop

+0

이것은 좋은 질문입니다. 나는 backgroundworkers로서 또 다른 옵션에 대해 생각 해본 적이 없다. 여러 가지 배경 지식 근로자가 같은 방법으로 변수에 액세스 할 때 threadnumber는 다른 작업자가 런타임에 재정의 할 수 있습니까? –

+0

스레드 간 재귀 호출이 너무 많이 일어나서 거기에서 일어날 수있는 일을 이해하지 못할 가능성이 높습니다. 당신은 당신의 메소드를 다른 메소드의 결과를 위해'async'와'await'으로 만들 수 있습니다. 그리고 나서 당신이 필요로하는만큼 여러 번 호출을 다시 시도하십시오. – Petaflop

답변

0

일반적으로 여러 스레드가 동일한 개체를 동시에 조작하도록 허용하는 것은 좋지 않습니다. 이것은 분명히 조작 된 객체의 상태에서 충돌을 야기 할 것입니다.

공유 변수 (예 : threadnumberretries)에 액세스하고 조작하는 행에 lock을 사용하는 것이 좋습니다.

  1. 그것은 각 작업자 스레드가 retries 배열에서 2 개 항목 (예 : threadnumberthreadnumber - 1)를 요구하는 것 같아 그래서, 당신은 호출 할 수 없습니다 때문에

    또한이 메소드를 호출하고있는 방법을 고려 GetXML 메서드가 연속적으로 threadnumber 값이거나 그렇지 않으면 retries 배열에 충돌이 발생합니다. 또는 아마도이 문제를 일으키는 코드의 버그 (아래 인용 된) 일 수 있습니다.

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

  2. GetXML 방법을 호출하는 코드를 고려하고 여러 노동자 동일한 threadnumber를 할당하지 않습니다 있는지 확인하십시오.

+1

'threadnumber'는 공유 변수가 아니라 매개 변수입니다. 그리고'retries'는 동시에 접근되는 반면에,'threadnumber-1' (항상 주석문에서 언급 한 경우를 제외하고는)으로 항상 색인화됩니다. 그래서 공유 변수 접근이 문제가되지는 않을 것입니다. –

+0

하지만 문제는 threadnumber ...라고 생각합니다. getxml (bla1, 1) 그리고 동시에 다음 작업자 getxml (bla2, 2) 및 메서드에서 threadnumber 재정의 할 수 있다고 생각합니까? –

0

논리적 인 실패 인 것으로 보입니다. 이제 각 스레드에 실제 변수 내용을 디버깅했습니다. 그래서 거기에 모두 괜찮아 보이고 변수를 무시할 수 있습니다.

그래서 코드를 편집하여 세 번째 시도가 끝나면 메소드가 중단됩니다.

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; 
     } 
    }