Я запускаю Parallel.For цикл на чуть более 7500 объектов. Внутри этого цикла я делаю несколько вещей для каждого из этих объектов, в частности, вызывая две веб-службы и два внутренних метода. Веб-службы просто проверяют объект, обрабатывают и возвращают строку, которую затем я устанавливаю как свойство объекта. То же самое касается двух внутренних методов.Parallel.For замерзает после 1370 итераций, не знаю почему
Я ничего не пишу на диск или не читаю с диска.
Я также обновляю пользовательский интерфейс в приложении 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% после замораживания.
@ Хенк Холтерман - требуется около 10-12 минут, чтобы добраться до 1360, и да, я могу проверить, что все эти записи обработаны, но не остальные записи.
@CodeInChaos - Спасибо, я попробую! Код действительно работает, если я вынимаю параллель, это просто навсегда и на один день. Я не пробовал ограничивать количество потоков, но буду.
EDIT 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 потока, которые все сидят на вызовах webservice. Я прочитал здесь http://www.albahari.com/threading/, что MaxThreads по умолчанию имеет значение 1023 для .Net 4 на 32-битной машине.
Как я могу освободить эти ожидающие темы, учитывая то, что у меня есть?
У меня была аналогичная проблема раньше - я бы попытался создать проект в режиме x86, чтобы увидеть, что это что-то изменит. Вы не могли бы сделать какой-либо InterOp в своих задачах? – BrokenGlass 2010-12-02 21:41:54
Замерзает или идет очень медленно. Как используется ЦП? – 2010-12-02 21:42:24
Не работали с TPL еще, но не можете ли вы просто сломать в отладчике и проверить, какой метод вызывает функции остановки? И работает ли код, если вы замените его на обычный цикл? И что произойдет, если вы используете `Parallel.For`, но ограничиваете его одним или двумя потоками? – CodesInChaos 2010-12-02 21:51:07