await operator - asynchronously await for a task to complete
The await
operator suspends evaluation of the enclosing async method until the asynchronous operation represented by its operand completes. When the asynchronous operation completes, the await
operator returns the result of the operation, if any. When the await
operator is applied to the operand that represents an already completed operation, it returns the result of the operation immediately without suspension of the enclosing method. The await
operator doesn't block the thread that evaluates the async method. When the await
operator suspends the enclosing async method, the control returns to the caller of the method.
In the following example, the HttpClient.GetByteArrayAsync method returns the Task<byte[]>
instance, which represents an asynchronous operation that produces a byte array when it completes. Until the operation completes, the await
operator suspends the DownloadDocsMainPageAsync
method. When DownloadDocsMainPageAsync
gets suspended, control is returned to the Main
method, which is the caller of DownloadDocsMainPageAsync
. The Main
method executes until it needs the result of the asynchronous operation performed by the DownloadDocsMainPageAsync
method. When GetByteArrayAsync gets all the bytes, the rest of the DownloadDocsMainPageAsync
method is evaluated. After that, the rest of the Main
method is evaluated.
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://learn.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 27700 bytes.
The operand of an await
expression must provide for notification when a task completes. In general, a delegate is invoked when the task completes, either successfully or unsuccessfully. The await
section of the C# language spec provides the details on how these notifications are implemented.
The preceding example uses the async Main
method. For more information, see the await operator in the Main method section.
Note
For an introduction to asynchronous programming, see Asynchronous programming with async and await. Asynchronous programming with async
and await
follows the task-based asynchronous pattern.
You can use the await
operator only in a method, lambda expression, or anonymous method that is modified by the async keyword. Within an async method, you can't use the await
operator in the body of a synchronous local function, inside the block of a lock statement, and in an unsafe context.
The operand of the await
operator is usually of one of the following .NET types: Task, Task<TResult>, ValueTask, or ValueTask<TResult>. However, any awaitable expression can be the operand of the await
operator. For more information, see the Awaitable expressions section of the C# language specification.
The type of expression await t
is TResult
if the type of expression t
is Task<TResult> or ValueTask<TResult>. If the type of t
is Task or ValueTask, the type of await t
is void
. In both cases, if t
throws an exception, await t
rethrows the exception.
Asynchronous streams and disposables
You use the await foreach
statement to consume an asynchronous stream of data. For more information, see the foreach
statement section of the Iteration statements article.
You use the await using
statement to work with an asynchronously disposable object, that is, an object of a type that implements an IAsyncDisposable interface. For more information, see the Using async disposable section of the Implement a DisposeAsync method article.
await operator in the Main method
The Main
method, which is the application entry point, can return Task
or Task<int>
, enabling it to be async so you can use the await
operator in its body. In earlier C# versions, to ensure that the Main
method waits for the completion of an asynchronous operation, you can retrieve the value of the Task<TResult>.Result property of the Task<TResult> instance that is returned by the corresponding async method. For asynchronous operations that don't produce a value, you can call the Task.Wait method. For information about how to select the language version, see C# language versioning.
C# language specification
For more information, see the Await expressions section of the C# language specification.