c#多线程程序与WebRequest
本文关键字:WebRequest 程序 多线程 | 更新日期: 2023-09-27 18:18:49
首先,我是论坛的新手,所以请对我和我的英语有一点耐心。: -)
我正在写一个c#应用程序,它应该发送多线程SOAP请求到apache后端。到目前为止,一切都很好,但我遇到了一个问题。应用程序首先读取一个XML文件从另一个系统,首先解析成类,排序并发送到SOAP后端。下面是代码片段
List<Thread> ThreadsPerOneRecord = new List<Thread>();
bool ExecuteSingleThreaded = false;
//The variable list is passed as parameter to the function
foreach (Record prov in list)
{
XMLResult.AppendText("Type: " + prov.Type + Environment.NewLine);
Thread t = new Thread(() => Send(prov, c));
t.Start();
//Here the sleep
Thread.Sleep(50);
ThreadsPerOneRecord.Add(t);
#region Code for test single threaded execution
if (ExecuteSingleThreaded)
{
foreach (Thread t2 in ThreadsPerOneRecord)
t2.Join();
ThreadsPerOneRecord.Clear();
}
#endregion
}
XMLResult.AppendText("Waiting for the threads to finish" + Environment.NewLine);
//Waiting for the threads to finish
foreach (Thread t in ThreadsPerOneRecord)
t.Join();
当我将此发送到SOAP web服务时,除了一个请求外,它工作得很好。这些请求彼此混淆在一起。例如:
What it should be:
Record 1 -> SOAP
Record 2 -> SOAP
Record 3 -> SOAP
What it is
Record 1 -> SOAP
Record 2 -> SOAP
Record 2 -> SOAP
Record 3 -> nowhere
我已经尝试调试整个代码,并与调试器它工作良好。当我插入50毫秒的睡眠时也是一样的。但如果没有睡眠,它会混合这两个记录…
有人知道为什么会这样吗?每个线程不应该独立于自身吗?我也检查了收集和数据是正确的。
感谢Oldfighter
Replace
Thread t = new Thread(() => Send(prov, c));
t.Start();
Thread t = new Thread(item => Send(item, c));
t.Start(prov);
在你的代码中lambda表达式实际上看到了迭代器变量的变化(它是每个线程的相同变量,而不是当你将lambda传递给线程构造函数时捕获的值)。
Classic foreach/capture;修复很简单——添加一个额外的变量:
foreach (Record tmp in list)
{
Record prov = tmp;
XMLResult.AppendText("Type: " + prov.Type + Environment.NewLine);
Thread t = new Thread(() => Send(prov, c));
否则," prove "在所有lambda之间共享。已经公开提到c# 5正在评估修复这个问题,但还没有确认。
您的问题是您正在访问Foreach循环中修改的闭包
:
List<Thread> ThreadsPerOneRecord = new List<Thread>();
bool ExecuteSingleThreaded = false;
//The variable list is passed as parameter to the function
foreach (Record prov in list)
{
var tempProv = prov;
XMLResult.AppendText("Type: " + tempProv.Type + Environment.NewLine);
Thread t = new Thread(() => Send(tempProv, c));
t.Start();
//Here the sleep
Thread.Sleep(50);
ThreadsPerOneRecord.Add(t);
#region Code for test single threaded execution
if (ExecuteSingleThreaded)
{
foreach (Thread t2 in ThreadsPerOneRecord)
t2.Join();
ThreadsPerOneRecord.Clear();
}
#endregion
}
XMLResult.AppendText("Waiting for the threads to finish" + Environment.NewLine);
//Waiting for the threads to finish
foreach (Thread t in ThreadsPerOneRecord)
t.Join();