Parallel.For зависает примерно после 1370 итераций, не знаю, почему

Я запускаю цикл Parallel.For для немногим более 7500 объектов. Внутри этого цикла for я выполняю ряд действий с каждым из этих объектов, в частности вызываю две веб-службы и два внутренних метода. Веб-службы просто проверяют объект, обрабатывают и возвращают строку, которую я затем устанавливаю как свойство объекта. То же самое и с двумя внутренними методами.

Я ничего не записываю на диск и не читаю с диска.

Я также обновляю пользовательский интерфейс в приложении winforms, добавляя метку и индикатор выполнения, чтобы пользователь знал, где это в. Вот код:

var task = Task.Factory.StartNew(() =>
{
  Parallel.For(0, upperLimit, (i, loopState) =>
  {
     if (cancellationToken.IsCancellationRequested)
        loopState.Stop();
     lblProgressBar.Invoke(
       (Action)
       (() => lblProgressBar.Text = string.Format("Processing record {0} of {1}.", (progressCounter++), upperLimit)));
     progByStep.Invoke(
       (Action)
       (() => progByStep.Value = (progressCounter - 1)));

      CallSvc1(entity[i]);
      Conversion1(entity[i]);
      CallSvc2(entity[i]);
      Conversion2(entity[i]);
  });
}, cancellationToken);

Это происходит на 32-битной машине Win7.

Есть идеи относительно того, почему это внезапно зависает, когда инкремент около 1370 или около того (это было 1361, 1365 и 1371)?

Любые идеи относительно того, как я могу отладить это и посмотреть, что блокируется?

EDIT:
Некоторые ответы на комментарии ниже:
@BrokenGlass - Нет, без взаимодействия. Я попробую компиляцию x86 и дам вам знать.

@chibacity - Поскольку это фоновая задача, пользовательский интерфейс не замораживается. До тех пор, пока он не зависнет, индикатор выполнения и метка будут двигаться примерно 2 раза в секунду. Когда он замерзает, он просто перестает двигаться. Я могу проверить, обработан ли номер, на котором он останавливается, но не более того. Использование ЦП на двухъядерном процессоре 2,2 ГГц минимально во время работы - 3-4% каждое и 1-2% после зависания.

@Henk Holterman - Чтобы добраться до 1360, требуется около 10-12 минут, и да, я может проверить, что все эти записи были обработаны, но не оставшиеся записи.

@CodeInChaos - Спасибо, я попробую! Код действительно работает, если я уберу параллель, это займет целую вечность и день. Я не пробовал ограничивать количество потоков, но буду.

РЕДАКТИРОВАТЬ 2:
Некоторые подробности относительно того, что происходит с веб-сервисами.

В основном, что происходит с веб-сервисами, это то, что они передают некоторые данные и получают данные (XmlNode). Затем этот узел используется в процессе Conversion1, который, в свою очередь, устанавливает другое свойство объекта, которое отправляется методу CallSvc2, и так далее. Это выглядит так:

private void CallSvc1(Entity entity)
{
    var svc = new MyWebService();
    var node = svc.CallMethod(entity.SomeProperty);
    entity.FieldToUpdate1.LoadXml(node.InnerXml);
}
private void Conversion1(Entity entity)
{
    // Do some xml inspection/conversion stuff
    if (entity.FieldToUpdate1.SelectSingleNode("SomeNode") == "something") {
        entity.FieldToUpdate2 = SomethingThatWasConverted;
    }
    else {
        // Do some more logic
    }
}
private void CallSvc2(Entity entity)
{
    var svc = new SomeOtherWebService();
    var xmlNode = svc.MethodToCall(entity.FieldToUpdate2.InnerXml);
    entity.AnotherXmlDocument.LoadXml(xmlNode.InnerXml);
}

Как видите, это довольно простой материал. В некоторых методах преобразования много чего происходит, но ни один из них не должен блокировать. И, как указано ниже, 1024 потока находятся в состоянии «ожидания», которые все сидят на вызовах веб-службы. Я прочитал здесь http://www.albahari.com/threading/ , что для MaxThreads по умолчанию установлено значение 1023 для .Net 4 на 32-битной машине.

Как я могу освободить эти ожидающие потоки, учитывая то, что у меня есть?

10
задан Chris Conway 3 December 2010 в 04:17
поделиться