我以这种方式使用Parallel.ForEach
:
public void myMethod(IEnumerable<MyType> paramIeCollection)
{
Parallel.Foreach(paramIeCollection,
(iterator) =>
{
//Do something
});
}
我想知道当paramIeCollection
为空时,Parallel.ForEach
无论如何都会启动并从线程池获取线程并消耗资源,或者如果它首先检查集合中是否有项目。
如果没有检查,为了避免这种情况,我在想这个代码:
if(paramIeCollection.count > 0)
{
//run Parallel.Foreach
}
所以问题是,在调用Parallel.ForEach
之前检查集合是否包含项目或者是否需要它是否是一个好习惯?
答案 0 :(得分:9)
事实是确实它确实检查。但是,如果您通过源代码,那么在它出现之前会有一些其他的检查和平衡。
如果你有处理器指令OCD ,事先像if(list.count > 0)
那样的简单检查可能会为你节省一堆IL。然而,在现实世界中,它不会产生太大的影响
System.Threading.Tasks
Reference Source
例如,对于简单IEnumberable
重载,您可以通过E.g
public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, Action<TSource> body)
private static ParallelLoopResult ForEachWorker<TSource, TLocal>(
IEnumerable<TSource> source,
ParallelOptions parallelOptions,
Action<TSource> body,
Action<TSource, ParallelLoopState> bodyWithState,
Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
Func<TLocal> localInit, Action<TLocal> localFinally)
内联呼叫
// This is an honest-to-goodness IEnumerable. Wrap it in a Partitioner and defer to our
// ForEach(Partitioner) logic.
return PartitionerForEachWorker<TSource, TLocal>(Partitioner.Create(source), parallelOptions, body, bodyWithState,
bodyWithStateAndIndex, bodyWithStateAndLocal, bodyWithEverything, localInit, localFinally);
// Main worker method for Parallel.ForEach() calls w/ Partitioners.
private static ParallelLoopResult PartitionerForEachWorker<TSource, TLocal>(
Partitioner<TSource> source, // Might be OrderablePartitioner
ParallelOptions parallelOptions,
Action<TSource> simpleBody,
Action<TSource, ParallelLoopState> bodyWithState,
Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
Func<TLocal> localInit,
Action<TLocal> localFinally)
最终检查
while (myPartition.MoveNext())
答案 1 :(得分:2)
Parallel.ForEach
将在内部调用IEnumerator.MoveNext()
,这将在空集合上返回false
,因此不会执行任何工作。
虽然直接检查集合是否为空是更快,但差异可能微不足道。