这是我正在运行的伪代码:
变种#1:
List<Task> tasks = new List<Task>();
foreach (...)
{
Task task = Task.Run(() =>
{
doWork();
});
tasks.Add(task);
}
Task.WhenAll(tasks.AsParallel()).ContinueWith((t) =>
{
// process results/handle errors
...
});
变体#2:
List<Task> tasks = new List<Task>();
foreach (...)
{
Task task = Task.Run(() =>
{
doWork();
});
tasks.Add(task);
}
Task.WhenAll(tasks.AsParallel()).Wait();
// process results/handle errors
...
我的问题是,为什么doWork
的调用方式在#1和#2之间显着地出现差异?是设计使然,我只是不了解它应该如何工作?
我(显然是失败的)理解/假设是,在两种情况下,doWork
将以多线程/异步的方式(如果可用)并行调用,唯一的区别是是调用代码将等待完成的时间有所不同。但是,实际执行任务的方式将是相同的,因为它们的调度/运行方式相同。
但是从调试两个版本的代码后我可以看出,变体#1导致doWork
以真正的并行/全多线程方式被调用,而变体#2的行为似乎像是每个任务的单线程顺序执行。
我想念什么?
答案 0 :(得分:3)
.AsParallel()
是LINQ
多线程扩展,与Task
无关。 Task.Run(...)
本身在大多数情况下就足够了,并且可以在有或没有LINQ
的情况下使用。
混用AsParallel()
和Task.Run()
是危险的事情,除非您确定自己在做什么:不加努力,它可能会严重降低性能,而不是使性能变差。
最后,请勿Wait()
Task
:将以常规同步方式强制执行它,从而抵消了Task
的所有好处。