await(C# 参考)
await 运算符应用于一个异步方法的任务挂起方法的执行,直到等待任务完成。任务表示正在进行的工作。
await 使用的异步方法必须被 异步 关键字修改。这样,方法是使用 async 修饰符和通常包含一个或多 await 表达式,引用 异步方法。
说明 |
---|
async 和 await 关键字在 Visual Studio 2012 中引入)。有关在该版本的新增功能的信息,请参见 Visual Studio 2012 中的新增功能。 有关异步编程的介绍,请参见 使用 Async 和 Await 的异步编程(C# 和 Visual Basic)。 |
await 运算符通常将应用的任务是从调用的返回值设置为实现的 基于任务的异步模式方法。示例包括类型 Task 或 Task<TResult>的值。
在下面的代码中,HttpClient 方法 GetByteArrayAsync 返回 Task<byte[]>,getContentsTask。当任务完成,任务是承诺生成实际字节数组。await 运算符在 SumPageSizesAsync 会应用于 getContentsTask 挂起执行,直到 getContentsTask 完成。同时,控件返回到 SumPageSizesAsync的调用方。当 getContentsTask 完成时,await 表达式计算为字节数组。
private async Task SumPageSizesAsync()
{
// To use the HttpClient type in desktop apps, you must include a using directive and add a
// reference for the System.Net.Http namespace.
HttpClient client = new HttpClient();
// . . .
Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
byte[] urlContents = await getContentsTask;
// Equivalently, now that you see how it works, you can write the same thing in a single line.
//byte[] urlContents = await client.GetByteArrayAsync(url);
// . . .
}
重要事项 |
---|
有关完整的示例,请参见演练:使用 Async 和 Await 访问 Web(C# 和 Visual Basic)。您可以从 开发人员代码示例 Microsoft 网站上的示例。此示例在 AsyncWalkthrough_HttpClient 项目。 |
由返回 Task<TResult>前面的示例所示,因此,如果 await 应用于方法的结果调用,然后 await 表达式的类型为 TResult。如果 await 应用于返回 Task方法的结果调用,则 await 表达式的类型无效。下面的示例演示差异。
// Keyword await used with a method that returns a Task<TResult>.
TResult result = await AsyncMethodThatReturnsTaskTResult();
// Keyword await used with a method that returns a Task.
await AsyncMethodThatReturnsTask();
await 表达式不阻止它在其上执行的线程。相反,它导致编译器注册异步方法的其余部分为等待的任务继续。然后控件回异步方法的调用方。当任务完成时,将会调用其延续任务,并且,异步方法的执行恢复它将会停止的位置。
await 表达式。async 修饰符指示一个直接封闭方法、lambda 表达式或匿名方法的主体只能发生。这个术语 等待 作为一个仅关键字在该上下文。在其他地方,则将该说明符解释为标识符。在方法、lambda 表达式或匿名方法内,await 表达式对象处于同步函数体不会发生,在查询表达式中,若 catch 或 finally 块 异常处理语句,在 lock 语句块,或者在 不安全 上下文。
异常
大多数异步方法返回 Task 或 Task<TResult>。返回的任务的属性传播有关其状态和历史记录的信息,例如任务是否已完成,异步方法是否引发异常或已取消,以及最终结果是。await 运算符访问这些属性。
如果等待导致异常的一个任务返回的异步方法,await 运算符再次引发异常。
如果等待取消的一个任务返回的异步方法,await 运算符再次引发 OperationCanceledException。
在出错状态的单一任务可能反映出多个异常。例如,任务可能为调用的结果。Task.WhenAll。当您等待此类任务,异常的等待操作再次引发只有一个。但是,您无法预测哪些异常来重新引发。
在中的错误处理异步方法的示例,请参见 try-catch(C# 参考)。
示例
以下 windows 窗体示例阐释如何在异步方法的 await,WaitAsynchronouslyAsync。对比度该方法的行为与 WaitSynchronously行为。不 await 运算符应用于任务,WaitSynchronously 尽管使用在定义的 async 修饰符和调用同步运行对其主体的 Thread.Sleep。
private async void button1_Click(object sender, EventArgs e)
{
// Call the method that runs asynchronously.
string result = await WaitAsynchronouslyAsync();
// Call the method that runs synchronously.
//string result = await WaitSynchronously ();
// Display the result.
textBox1.Text += result;
}
// The following method runs asynchronously. The UI thread is not
// blocked during the delay. You can move or resize the Form1 window
// while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
await Task.Delay(10000);
return "Finished";
}
// The following method runs synchronously, despite the use of async.
// You cannot move or resize the Form1 window while Thread.Sleep
// is running because the UI thread is blocked.
public async Task<string> WaitSynchronously()
{
// Add a using directive for System.Threading.
Thread.Sleep(10000);
return "Finished";
}
请参见
任务
演练:使用 Async 和 Await 访问 Web(C# 和 Visual Basic)