C Sharp/The .NET Framework/async
< C Sharp
語法
編輯運算符await
掛起(suspend)對其後運算數中的async方法(或者async Task對象)的求值,直至async方法包含的異步操作完成才返回其運算數的值(如果有)。如果一個async方法被運算符await
掛起,則該方法的caller獲得控制權恢復執行。async方法中的異常會在運算符await
中重新拋出(rethrow)。
直觀的示例:
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class AwaitOperator
{
public static async Task Main()
{
Task<int> downloading = DownloadDocsMainPageAsync();
Console.WriteLine($"{nameof(Main)}: Launched downloading.");
int bytesLoaded = await downloading;
Console.WriteLine($"{nameof(Main)}: Downloaded {bytesLoaded} bytes.");
}
private static async Task<int> DownloadDocsMainPageAsync()
{
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: About to start downloading.");
var client = new HttpClient();
byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/");
Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: Finished downloading.");
return content.Length;
}
}
// Output similar to:
// DownloadDocsMainPageAsync: About to start downloading.
// Main: Launched downloading.
// DownloadDocsMainPageAsync: Finished downloading.
// Main: Downloaded 126809 bytes.
await foreach
語句消費異步數據流。
await using
語句在異步可回收(disposable)對象上工作。
例子
編輯using System;
using System.Threading.Tasks;
namespace AsyncWarning
{
class Program
{
static async Task Main()
{
Console.WriteLine("Entering Main() application entry point.");
int millisecondsDelay = 2000;
await CallingMethodAsync(millisecondsDelay);
Console.WriteLine("Exiting Main() application entry point.");
await Task.Delay(millisecondsDelay + 500);
}
static async Task CallingMethodAsync(int millisecondsDelay)
{
Console.WriteLine(" Entering calling method.");
// Call #1.
// Call an async method. Because you don't await it, its completion
// isn't coordinated with the current method, CallingMethodAsync.
// The following line causes warning CS4014.
// CalledMethodAsync(millisecondsDelay);
// Call #2.
// To suppress the warning without awaiting, you can assign the
// returned task to a variable. The assignment doesn't change how
// the program runs. However, recommended practice is always to
// await a call to an async method.
// Replace Call #1 with the following line.
//Task delayTask = CalledMethodAsync(millisecondsDelay);
// Call #3
// To contrast with an awaited call, replace the unawaited call
// (Call #1 or Call #2) with the following awaited call. Best
// practice is to await the call.
// await CalledMethodAsync(millisecondsDelay);
Console.WriteLine(" Returning from calling method.");
}
static async Task CalledMethodAsync(int millisecondsDelay)
{
Console.WriteLine(" Entering called method, starting and awaiting Task.Delay.");
await Task.Delay(millisecondsDelay);
Console.WriteLine(" Task.Delay is finished--returning from called method.");
}
}
// Output with Call #1 or Call #2. (Wait for the last line to appear.)
// Entering Main() application entry point.
// Entering calling method.
// Entering called method, starting and awaiting Task.Delay.
// Returning from calling method.
// Exiting Main() application entry point.
// Task.Delay is finished--returning from called method.
// Output with Call #3, which awaits the call to CalledMethodAsync.
// Entering Main() application entry point.
// Entering calling method.
// Entering called method, starting and awaiting Task.Delay.
// Task.Delay is finished--returning from called method.
// Returning from calling method.
// Exiting Main() application entry point.
}