Могу ли я быть уверен, что каждый вызов DoSomethingWithObject завершен до того, как ForEach вернется, или мне нужно использовать WaitHandles самостоятельно?
Parallel.ForEach
является блокирующим вызовом.Он не вернется, пока не будет завершена каждая итерация.
Есть ли что-то эквивалентное WaitHandle.WaitAll(...);
?
Да, более или менее.На самом деле он не будет использовать WaitHandle.WaitAll
, потому что 1) он будет ужасно неэффективным и 2) он не масштабируется, поскольку имеет ограничение в 64 дескриптора.Есть несколько очень масштабируемых методов для ожидания выполнения нескольких задач.Один из моих любимых - использовать CountdownEvent
. 1
Вот как это работает.Используйте свое воображение и притворяйтесь, что Parallel.ForEach
превращается в следующий код. 2
var finished = new CountdownEvent(1);
foreach (var item in collection)
{
var capture = item;
finished.AddCount();
Task.Factory.StartNew(
() =>
{
try
{
DoSomething(capture);
}
finally
{
finished.Signal();
}
});
}
finished.Signal();
finished.Wait();
1 Я не говорю, что это используемая техникана Parallel.ForEach
, но, вероятно, что-то похожее.
2 На самом деле Parallel.ForEach
реализовано гораздо более сложным образом.Я только пытаюсь помочь вам представить, как он может ждать завершения каждой итерации.