任务执行取决于等待机制吗?

时间:2019-04-17 19:03:06

标签: c# multithreading plinq

这是我正在运行的伪代码:

变种#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的行为似乎像是每个任务的单线程顺序执行。

我想念什么?

1 个答案:

答案 0 :(得分:3)

.AsParallel()LINQ多线程扩展,与Task无关。 Task.Run(...)本身在大多数情况下就足够了,并且可以在有或没有LINQ的情况下使用。

混用AsParallel()Task.Run()是危险的事情,除非您确定自己在做什么:不加努力,它可能会严重降低性能,而不是使性能变差。

最后,请勿Wait() Task:将以常规同步方式强制执行它,从而抵消了Task的所有好处。