首先,让我们澄清一些术语:“异步”(async)意味着它可以在启动之前将控制权交还给调用线程。在异步方法中,这些“yield”点是await表达式。
这与术语“异步”非常不同,多年来,MSDN文档使用(mis)来表示“在后台线程上执行”。
为了进一步混淆这个问题,async与“awaitable”非常不同;有一些异步方法的返回类型是不可等待的,还有许多方法返回的可等待类型不是异步的。
他们不是什么已经够多了;以下是它们:
async关键字允许使用异步方法(也就是说,它允许await表达式)。异步方法可以返回Task, Task<T>,或者(如果必须的话)void。
任何遵循特定模式的类型都是可等待的。最常见的可等待类型是Task和Task<T>。
因此,如果我们将您的问题重新表述为“如何以一种可等待的方式在后台线程上运行操作”,答案是使用Task。运行:
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;
}
So, the basic pattern of things is to have async code depend on "awaitables" in its await expressions. These "awaitables" can be other async methods or just regular methods returning awaitables. Regular methods returning Task/Task<T> can use Task.Run to execute code on a background thread, or (more commonly) they can use TaskCompletionSource<T> or one of its shortcuts (TaskFactory.FromAsync, Task.FromResult, etc). I don't recommend wrapping an entire method in Task.Run; synchronous methods should have synchronous signatures, and it should be left up to the consumer whether it should be wrapped in a 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/await介绍;最后是一些很好的后续资源。异步的MSDN文档也非常好。