Parallel.ForEach будет блокироваться до тех пор, пока все элементы не будут обработаны - похоже, здесь нужно вызывать RaiseAllDoneEvent () из вызывающей стороны сразу после вызова Parallel.ForEach:
List<Item> _Items = GetItems();
System.Threading.Tasks.Parallel.ForEach(_Items, (i) =>
{
DoSomething(i);
});
RaiseAllDoneEvent();
Другими словами, не нужно вообще отсчитывать (или отслеживать, сколько предметов нужно обработать).Если вы хотите, чтобы параллельные операции не блокировались, вы можете превратить их в кучу задач:
List<Item> _Items = GetItems();
Task.Factory.StartNew(()=> {
Task.WaitAll(
_Items.Select(i => Task.Factory.StartNew(() => DoSomething(i))).ToArray()
);
}).ContinueWith(t => RaiseAllDoneEvent());
В этом случае вы начнете запускать внешнюю задачу, а затем подождать кучузадач (по одному для каждого элемента), а затем, наконец, поднять все готовое событие.Ничто из этого не блокирует первоначального абонента.