应该等待 Parallel.Foreach 吗?
Should Parallel.Foreach be waited?
这里发生了一件奇怪的事情。我以为 Parallel.Foreach 会等到所有任务完成后再继续。但是,我有类似的东西:
List<string> foo(List<A> list){
Dictionary<string, bool> dictionary = new Dictionary<string, bool>();
Parallel.Foreach(list, element =>
{
dictionary[element.Id] = true;
if (element.SomeMethod()){
dictionary[element.Id] = false;
}
});
List<string> selectedIds = (from element in list where !dictionary[element.Id] select element.Id).ToList();
return selectedIds;
}
然后我在 select 行中得到 System.Collections.Generic.KeyNotFoundException(有时,不总是)。如您所见,我正在为每个可能的键(列表元素的 ID)初始化字典,然后得到这个异常,这让我认为在 Parallel.Foreach 执行完成之前可能会到达这一行。 .. 那正确吗?如果是这样,我如何才能等到 Parallel.Foreach 的所有分支都完成?
Parallel.Foreach
不需要等待,因为它不是 return 和 Task
并且不是异步的。当对该方法的调用完成时,迭代已经完成。
但是,Parallel.Foreach
同时使用多个线程并且 Dictionary
不是线程安全的。
您可能手上有竞争条件,您应该改用线程安全 ConcurrentDictionary
。
这个具体案例可以通过使用 PLinq 的 AsParallel
:
以更简单的方式解决
list.AsParallel().Where(element => !element.SomeMethod());
这里发生了一件奇怪的事情。我以为 Parallel.Foreach 会等到所有任务完成后再继续。但是,我有类似的东西:
List<string> foo(List<A> list){
Dictionary<string, bool> dictionary = new Dictionary<string, bool>();
Parallel.Foreach(list, element =>
{
dictionary[element.Id] = true;
if (element.SomeMethod()){
dictionary[element.Id] = false;
}
});
List<string> selectedIds = (from element in list where !dictionary[element.Id] select element.Id).ToList();
return selectedIds;
}
然后我在 select 行中得到 System.Collections.Generic.KeyNotFoundException(有时,不总是)。如您所见,我正在为每个可能的键(列表元素的 ID)初始化字典,然后得到这个异常,这让我认为在 Parallel.Foreach 执行完成之前可能会到达这一行。 .. 那正确吗?如果是这样,我如何才能等到 Parallel.Foreach 的所有分支都完成?
Parallel.Foreach
不需要等待,因为它不是 return 和 Task
并且不是异步的。当对该方法的调用完成时,迭代已经完成。
但是,Parallel.Foreach
同时使用多个线程并且 Dictionary
不是线程安全的。
您可能手上有竞争条件,您应该改用线程安全 ConcurrentDictionary
。
这个具体案例可以通过使用 PLinq 的 AsParallel
:
list.AsParallel().Where(element => !element.SomeMethod());