有以下方法,
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();
这两者有什么区别?
当您运行(在标记为async
的方法内(时
await DoWork1Async();
您的代码在编译器设置的状态机中调用DoWork1Async
。在这一点上,您的代码将控制权交还给那个状态机。任务完成后,方法中的其余代码将继续。
请记住,async
代码不一定在单独的线程上运行(例如,如果您正在执行异步I/O(。
运行时:
await Task.Run(() => DoWork1Async());
将您的DoWork1Async
作为工作分派到线程池。它在不同的线程(线程池线程(上执行。当这项工作完成后,相同的状态机机制将控制权交还给代码以继续运行。
在第二种情况下,代码总是在线程池线程上运行。在第一种情况下,您可能根本没有使用额外的线程(取决于DoWork1Async的编码方式(
await Task.Run(() => DoWork1Async());
启动一个Task,该Task将调用DoWork1Async
。无论DoWork1Async
是如何实现的,这都保证是异步的。
注意:CCD_ 7返回一个CCD_,而不是CCD_ 9。当lambda返回Task时,Task。Run((返回一个任务,该任务完成后会得到内部任务的结果。因此,您不需要做像await await Task.Run(() => return a Task)
这样尴尬的事情。
await DoWork1Async();
在当前线程上同步调用DoWork1Async
。如果DoWork1Async
执行await
语句,那么工作将被挂起,其余的工作将异步进行。但是,如果DoWork1Async
在未命中await
的情况下完成执行,则控制将返回给调用方,然后将全部同步启动DoWork2Async
。
简而言之,第一种形式保证DoWork1Async不会同步启动或完成。
第二个表单将同步启动DoWork1Async,甚至可能同步完成它,这取决于它的编写方式。
--这里有一把小提琴显示了差异:
https://dotnetfiddle.net/GhrO8x
请注意,在第一种情况下,DoWork()
是如何在我们等待其Task
之前完全同步启动和执行的,而在第二种情况中,它是在我们等待它的任务之后异步执行的。