C # многопоточная программа с WebRequest - PullRequest
3 голосов
/ 27 декабря 2011

Во-первых, я новичок в форуме, поэтому, пожалуйста, немного терпения со мной и моим английским.: -)

Я пишу приложение на 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, он работает нормально, за исключением одного запроса.Эти запросы перепутаны между собой.Т.е.:

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

Ответы [ 3 ]

6 голосов
/ 27 декабря 2011

Заменить

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

с

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

В вашем коде лямбда-выражение фактически видит изменения в переменной итератора (это одна и та же переменная для каждого потока, а не значение, захваченное при передаче лямбды в конструктор потока).

4 голосов
/ 27 декабря 2011

Классический foreach / capture; исправить легко - добавьте дополнительную переменную:

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

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

В противном случае «prov» распределяется между всеми лямбдами. Было публично упомянуто, что исправление это оценивается для c # 5, но еще не подтверждено в любом случае.

4 голосов
/ 27 декабря 2011

ваша проблема в том, что вы обращаетесь к измененному замыканию в цикле 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(); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...