首先,让我们澄清一些术语:“异步”(
async)表示它可以在启动之前将控制权交还给调用线程。在一种
async方法中,那些“屈服”点是
await表达式。
这与“异步”一词有很大不同,因为MSDN文档使用(多年来)表示“在后台线程上执行”。
进一步混淆这个问题,
async与“等待”有很大不同;有一些
async方法的返回类型不可等待,而许多方法的返回类型则不是
async。
足够了他们 不是 。这里是他们什么 是 :
- 所述
async
关键字允许异步方法(即,它允许await
表达式)。async
方法可能会返回Task
,Task<T>
或(如果必须)void
。 - 遵循特定模式的任何类型都是可以等待的。最常见的等待类型是
Task
和Task<T>
。
因此,如果我们将您的问题重新表述为“如何以一种可以等待的方式 在后台线程上 运行操作”,答案是使用
Task.Run:
private Task<int> DoWorkAsync() // No async because the method does not need await{ return Task.Run(() => { return 1 + 2; });}(但是这种模式是一种糟糕的方法;请参见下文)。
但是,如果您的问题是“我如何创建一种
async可以让其返回给调用者而不是阻塞的方法”,则答案是声明该方法
async并
await用于其“收益”点:
private async Task<int> GetWebPageHtmlSizeAsync(){ var client = new HttpClient(); var html = await client.GetAsync("http://www.example.com/"); return html.Length;}因此,事物的基本模式是使
async代码依赖于其
await表达式中的“ awaitables”
。这些“等待项”可以是其他
async方法,也可以是返回等待项的常规方法。常规方法返回
Task/
Task<T>可
使用
Task.Run到在后台线程执行代码,或(更常见),他们可以用
TaskCompletionSource<T>或它的快捷方式(之一
TaskFactory.FromAsync,
Task.FromResult等等)。我
不 建议在中包装整个方法
Task.Run;同步方法应具有同步签名,是否应将其包装在
Task.Run:
private int DoWork(){ return 1 + 2;}private void MoreSynchronousProcessing(){ // Execute it directly (synchronously), since we are also a synchronous method. var result = DoWork(); ...}private async Task DoVariousThingsFromTheUIThreadAsync(){ // I have a bunch of async work to do, and I am executed on the UI thread. var result = await Task.Run(() => DoWork()); ...}我的博客上有一个
async/
awaitintro;最后是一些很好的后续资源。的MSDN文档
async也非常出色。



