我一直在试验 Parallel.For。特别是支持线程本地数据的重载,例如
public static System.Threading.Tasks.ParallelLoopResult For (long fromInclusive, long toExclusive, System.Threading.Tasks.ParallelOptions parallelOptions, Func localInit, Func body, Action localFinally);
根据documentation
The localInit delegate is invoked once for each thread that participates in the loop's execution
但是我认为我下面的例子与它相矛盾
var threads = new ConcurrentBag<int>();
ValueTuple LocalInit()
{
threads.Add(Thread.CurrentThread.ManagedThreadId);
return new System.ValueTuple();
}
ValueTuple Body(long i, ParallelLoopState _, ValueTuple state)
{
Thread.Sleep(100);
return state;
}
void LocalFinally(ValueTuple state) { };
Parallel.For(0L, 1000L, new ParallelOptions(), LocalInit, Body, LocalFinally);
Console.WriteLine($"{threads.Count} inits between {threads.Distinct().Count()} threads");
它打印一条消息,例如
79 inits between 13 threads
这是怎么回事?
最佳答案
尝试录制任务 ID Task.CurrentId
而不是线程ID。
var threads = new ConcurrentBag<int>();
var tasks = new ConcurrentBag<int>();
ValueTuple LocalInit()
{
threads.Add(Thread.CurrentThread.ManagedThreadId);
tasks.Add(Task.CurrentId ?? throw new Exception());
return new System.ValueTuple();
}
ValueTuple Body(long i, ParallelLoopState _, ValueTuple state)
{
Thread.Sleep(100);
return state;
}
void LocalFinally(ValueTuple state) { };
Parallel.For(0L, 1000L, new ParallelOptions(), LocalInit, Body, LocalFinally);
Console.WriteLine($"{threads.Count} inits between {threads.Distinct().Count()} threads");
Console.WriteLine($"{tasks.Count} inits between {tasks.Distinct().Count()} tasks");
这打印
87 inits between 16 threads
87 inits between 87 tasks
文档是错误的。他们应该说
The localInit delegate is invoked once for each task that participates in the loop's execution
可以有比线程更多的任务。总是线程数 ≤ 任务数 ≤ 迭代次数。
关于.net - Parallel.For 多久调用一次 localInit?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51748047/