Task.WhenAll是否在后台线程并行运行任务

4
以下两个代码片段是否执行相同的操作?
//--------------------------------------------------
1.
//--------------------------------------------------

var producer = Task.Run(async () =>
{
    await bar.ReadDataAsync();
});

var consumer = Task.Run(async () =>
{
    await bar.WriteDataAsync();
});


await Task.WhenAll(consumer, producer);

//--------------------------------------------------
2.
//--------------------------------------------------

await Task.WhenAll(bar.ReadDataAsync(), bar.WriteDataAsync());

是的,两个已经运行的任务并行执行,然后在waitall调用后合并结果。 - Niranjan Singh
并不完全相同。1)创建了四个任务+1个WhenAll。2)创建了两个任务+1个WhenAll。 - norekhov
但是方法2不会在当前线程中运行两个任务,基本上竞争调度时间吗? - rudimenter
1
顺便提一句,关于示例(1),假设ReadDataAsyncWriteDataAsync返回的是Task(而不仅仅是可等待对象),你不需要将它们包装在Task.Run()中。在大多数情况下,var producer = bar.ReadDataAsync()就足够了,并且更有意义。 - shay__
2个回答

6

Task.WhenAll并不会运行任务,这个方法不会启动任何任务。

它实际上返回一个新的Task,只有当所有原始任务都完成时才会完成。

来自msdn:

Task.WhenAll 方法

.NET Framework 4.6 和 4.5

创建一个任务,在所有提供的任务都完成后完成。

https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task.whenall%28v=vs.110%29.aspx

在你的示例中,你调用了Task.Run。这是一个异步运行工作单元的请求。然而,线程关联性不能保证。两个工作单元可能会同步运行-这取决于默认的TaskScheduler


两个工作单元都可以同步运行 - 这是我通过测试得出的结论。因此,基本上第二个版本不会启动2个后台线程并以真正的多线程方式运行它们。 - rudimenter
1
@rudimenter 异步IO调用是真正的并行形式 - 它们不会启动线程,因为它们不需要线程。可以说,第一个版本需要无谓地使用后台线程。 - Gusdor

-5

Task.WhenAll 没有什么神奇的地方 - 它只是像其他方法一样的一个方法。

因此,首先评估其所有参数,然后才执行该方法本身。所以,是的,你可以获得并行执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接