这是我正在运行的伪代码:
变体#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似乎表现得像是单线程,顺序执行每项任务。
我错过了什么?
.AsParallel()
是LINQ
多线程扩展,它与Task
无关。 Task.Run(...)
本身就足以满足大多数情况,可以使用或不使用LINQ
。
将AsParallel()
和Task.Run()
混合起来是很危险的事情,除非你确定你在做什么:没有努力它可能会显着降低你的表现,而不是像你期望的那样使它变得更好。
最后,不要Wait()
Task
:它将以常规的同步方式强制执行,从而取消所有Task
的好处。