我试图以最简单的形式理解异步等待。为了这个示例,我想创建一个非常简单的方法,将两个数字相加,当然,这根本没有处理时间,这只是在此处举例说明的问题。
private async Task DoWork1Async() { int result = 1 + 2; }
private async Task DoWork2Async() { Task.Run( () => { int result = 1 + 2; }); }
如果我等待DoWork1Async(),代码将同步还是异步运行?
DoWork1Async()
是否需要包装同步代码Task.Run以使该方法可以等待和异步,以免阻塞UI线程?
Task.Run
我试图弄清楚我的方法是a Task还是return Task<T>,是否需要包装代码Task.Run以使其异步。
Task
Task<T>
我确定是个愚蠢的问题,但我在网上看到的例子是人们在等待没有异步且没有包装在Task.Run或中的代码StartNew。
StartNew
首先,让我们澄清一些术语:“异步”(async)表示它可以在启动之前将控制权交还给调用线程。在一种async方法中,那些“屈服”点是await表达式。
async
await
这与“异步”一词有很大不同,因为MSDN文档使用(多年来)表示“在后台线程上执行”。
进一步混淆这个问题,async与“等待”有很大不同;有一些async方法的返回类型不可等待,而许多方法的返回类型则不是async。
足够了他们 不是 。这里是他们什么 是 :
void
因此,如果我们将您的问题重新表述为“如何以一种可以等待的方式 在后台线程上 运行操作”,答案是使用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:
TaskCompletionSource<T>
TaskFactory.FromAsync
Task.FromResult
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也非常出色。