如果源为空,Parallel.ForEach 是否启动线程?
Does Parallel.ForEach start threads if the source is empty?
我是这样使用 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
之前检查集合是否有项目是一个好习惯,还是不需要?
说实话它确实会检查。但是,如果您浏览源代码,就会发现一些其他 制衡 它会在弄清楚之前进行。
如果您有 处理器指令 OCD,像 if(list.count > 0)
这样的简单事先检查可能会为您节省大量 IL。然而在现实世界中它不会有太大的不同
System.Threading.Tasks
Reference Source
例如,对于简单的 IEnumerable
重载,您可以通过 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())
Parallel.ForEach
将在内部调用 IEnumerator.MoveNext()
,这将 return false
用于空集合,因此不会完成任何工作。
虽然直接检查集合是否为空会更快,但差异可以忽略不计。
我是这样使用 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
之前检查集合是否有项目是一个好习惯,还是不需要?
说实话它确实会检查。但是,如果您浏览源代码,就会发现一些其他 制衡 它会在弄清楚之前进行。
如果您有 处理器指令 OCD,像 if(list.count > 0)
这样的简单事先检查可能会为您节省大量 IL。然而在现实世界中它不会有太大的不同
System.Threading.Tasks
Reference Source
例如,对于简单的 IEnumerable
重载,您可以通过 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())
Parallel.ForEach
将在内部调用 IEnumerator.MoveNext()
,这将 return false
用于空集合,因此不会完成任何工作。
虽然直接检查集合是否为空会更快,但差异可以忽略不计。