有以下方法,
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();
这两者有什么区别?
答案 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的编码方式)