C# 几个后台工作线程相同的方法
本文关键字:线程 方法 工作 后台 几个 | 更新日期: 2023-09-27 17:56:23
我有一个问题,当 2-8 个后台工作人员访问相同的方法时出现问题。所以这里有一个例子:
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 字符串和线程编号 1-8 调用该方法 getxml。我的问题是,有时重试次数达到 5 或更高。所以我认为后台工作者有时会访问相同的变量并计算它?
允许多个线程同时操作同一对象通常不是一个好主意。这肯定会在纵对象的状态下引起冲突。
考虑lock
在共享变量(即 threadnumber
和retries
)被访问和操作。
还要考虑调用方法的方式,因为:
-
似乎每个工作线程都需要
retries
数组中的 2 个条目(即threadnumber
和threadnumber - 1
) 因此,您不能使用连续的threadnumber
值调用GetXML
方法,否则您将在retries
数组中发生冲突。或者,这可能是导致此问题的代码中的错误(下面引用)。如果(重试次数 [线程数 - 1]>= 4) 重试次数[线程数] = 1;
-
请考虑调用
GetXML
方法的代码,并确保它不会将相同的threadnumber
分配给多个工作线程。
这似乎是一个逻辑上的失败。 现在我已经调试了每个线程和实际的变量内容。 所以似乎一切都很好,没有变量可以被覆盖。
因此,我编辑了代码,以便在第三次重试后该方法中止。
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;
}
}