Я запускаю цикл Parallel.For на чуть более 7500 объектов. Внутри этого цикла я делаю несколько вещей для каждого из этих объектов, в частности, вызывая две веб-службы и два внутренних метода. Веб-службы просто проверяют объект, обрабатывают и возвращают строку, которую затем я устанавливаю как свойство объекта. То же самое касается двух внутренних методов.
Я ничего не пишу на диск или не читаю с диска.
Я также обновляю интерфейс в приложении 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 - требуется около 10-12 минут, чтобы добраться до 1360, и да, я могу проверить, что все эти записи обработаны, но не остальные записи.
@CodeInChaos - Спасибо, я попробую! Код действительно работает, если я вынимаю параллель, это просто навсегда и на один день. Я не пробовал ограничивать количество потоков, но будет.
РЕДАКТИРОВАТЬ 2:
Некоторые сведения о том, что происходит с веб-сервисами
В основном, что происходит с веб-службами, это то, что они передают некоторые данные и получают данные (XmlNode). Этот node затем используется в процессе 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 потока, которые все сидят на вызовах webservice. Я читал здесь http://www.albahari.com/threading/, что MaxThreads по умолчанию имеет значение 1023 для .Net 4 на 32-битной машине.
Как я могу отпустить эти ожидающие потоки, учитывая то, что у меня есть?