首先我是论坛的新人,所以请耐心等待我和我的英语。 : - )
我正在编写一个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
答案 0 :(得分:6)
替换
Thread t = new Thread(() => Send(prov, c));
t.Start();
与
Thread t = new Thread(item => Send(item, c));
t.Start(prov);
在你的代码中,lambda表达式实际上看到了对iterator变量的更改(它是每个线程的相同变量,而不是将lambda传递给线程构造函数时捕获的值)。
答案 1 :(得分:4)
您的问题是您在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();
答案 2 :(得分:4)
经典的foreach / capture;修复很简单 - 添加一个额外的变量:
foreach (Record tmp in list)
{
Record prov = tmp;
XMLResult.AppendText("Type: " + prov.Type + Environment.NewLine);
Thread t = new Thread(() => Send(prov, c));
否则,所有lambda之间共享“prov”。已经公开提到,正在对c#5进行评估,但尚未确认。