使用await Task.Run(()=> DoWork1Async())而不是使用await DoWork1Async()吗?

时间:2018-12-03 19:44:20

标签: c#

有以下方法,

async Task DoWork1Async() { .... };
async Task DoWork2Async() { .... };
async Task DoWork3Async() { .... };

我阅读了以下代码

await Task.Run(() => DoWork1Async());
await Task.Run(() => DoWork2Async());
await Task.Run(() => DoWork3Async());

代替

await DoWork1Async();
await DoWork2Async();
await DoWork3Async();

这两者有什么区别?

2 个答案:

答案 0 :(得分:2)

await Task.Run(() => DoWork1Async());

启动一个任务,该任务将调用DoWork1Async。无论如何实现DoWork1Async,这都是异步的。

注意Task.Run(Action<Task<T>>)返回一个Task<T>,         不是一个Task<Task<T>>。当您的lambda返回Task时,Task.Run()返回一个Task,该任务以内部任务的结果完成。因此,您不需要做诸如await await Task.Run(() => return a Task)这样的笨拙的事情。


await DoWork1Async();

在当前线程上同步调用DoWork1Async。如果DoWork1Async执行await语句,则工作将被挂起,其余工作将异步进行。但是,如果DoWork1Async完成执行而没有击中await,则控制权将返回给您的调用者,然后将同步启动DoWork2Async


因此,简而言之,第一种形式确保DoWork1Async不会同步开始或完成。

第二种形式将同步启动DoWork1Async,甚至可以根据其编写方式同步完成它。

- 这是一个显示差异的小提琴:

https://dotnetfiddle.net/GhrO8x

请注意,在第一种情况下DoWork()是如何启动并完全同步执行的,甚至还没有等待它的Task,而在第二种情况下,它是在等待任务后异步执行的。

答案 1 :(得分:1)

运行时(在标记为async的方法内)

 await DoWork1Async();

您的代码在编译器设置的状态机中调用DoWork1Async。那时,您将代码放回了该状态机的控制权。任务完成后,方法中的其余代码将继续。

请记住,async代码不一定在单独的线程上运行(例如,如果您正在执行异步I / O)。

运行时:

 await Task.Run(() => DoWork1Async());

您的DoWork1Async作为工作被分派到线程池。它在其他线程(线程池线程)上执行。完成该工作后,相同的状态机机制会将控制权交还给您代码以继续运行。

在第二种情况下,您的代码始终在线程池线程上运行。在第一种情况下,您可能根本没有使用额外的线程(取决于DoWork1Async的编码方式)