简体   繁体   English

使用WebRequest的C#多线程程序

[英]C# multi-threading program with WebRequest

First I am new in the forum so please have a little bit patience with me and my english. 首先,我是论坛的新人,所以请耐心等待我和我的英语。 :-) :-)

I am writing a C# application which should send multithreaded SOAP requests to an apache backend. 我正在编写一个C#应用程序,它应该将多线程SOAP请求发送到apache后端。 Everything worked fine till now but I ran into a problem. 到目前为止一切工作正常,但我遇到了问题。 The application first reads a XML file from another system that is parsed first into classes, sorted and send to the SOAP backend. 应用程序首先从另一个系统读取XML文件,该系统首先被解析为类,然后排序并发送到SOAP后端。 Here the snippet 这里的片段

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(); 

As I am sending this to the SOAP web service it works fine except one request. 当我将它发送到SOAP Web服务时,除了一个请求之外它工作正常。 These requests are mixed up between each other. 这些请求彼此混淆。 Ie: 即:

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

I already tried to debug the whole code and with the debugger it works fine. 我已经尝试调试整个代码,并使用调试器工作正常。 The same when I insert this sleep of 50 milliseconds. 当我插入50毫秒的睡眠时也一样。 But without the sleep it mixes this two records ... 但没有睡眠就混合了这两个记录......

Does anybody have any idea why this happens? 有没有人知道为什么会这样? Shouldn't every thread be independent from itself? 不应该每个线程都独立于自身吗? Also I checked the collection and the data are correctly inside. 我也检查了集合,数据正确在里面。

Thanks 谢谢

Oldfighter Oldfighter

Replace 更换

Thread t = new Thread(() => Send(prov, c));
t.Start();

with

Thread t = new Thread(item => Send(item, c));
t.Start(prov);

In your code lambda expression actually sees changes to iterator variable (it's the same variable for every thread, not value captured when you passed lambda to thread constructor). 在你的代码中,lambda表达式实际上看到了对iterator变量的更改(它是每个线程的相同变量,而不是将lambda传递给线程构造函数时捕获的值)。

your problem is that you are accessing a modified closure in your Foreach loop 你的问题是你正在访问Foreach循环中的修改后的闭包

here is the fix: 这是修复:

        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(); 

Classic foreach/capture; 经典的foreach /捕获; fix is easy - add an extra variable: 修复很简单 - 添加一个额外的变量:

foreach (Record tmp in list)
{
  Record prov = tmp;
  XMLResult.AppendText("Type: " + prov.Type + Environment.NewLine);

  Thread t = new Thread(() => Send(prov, c));                      

Otherwise, "prov" is shared between all the lambdas. 否则,所有lambda之间共享“prov”。 It has been publicly mentioned that fixing this is being evaluated for c# 5, but not yet confirmed either way. 已经公开提到,正在对c#5进行评估,但尚未确认。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM