await (C# Reference)

The await operator is applied to a task in an asynchronous method to insert a suspension point in the execution of the method until the awaited task completes. The task represents ongoing work.

await can only be used in an asynchronous method modified by the async keyword. Such a method, defined by using the async modifier and usually containing one or more await expressions, is referred to as an async method.

Note

The async and await keywords were introduced in C# 5. For an introduction to async programming, see Asynchronous Programming with async and await.

The task to which the await operator is applied typically is returned by a call to a method that implements the Task-Based Asynchronous Pattern. They include methods that return Task, Task<TResult>, and System.Threading.Tasks.ValueType<TResult> objects.

In the following example, the HttpClient.GetByteArrayAsync method returns a Task<byte[]>. The task is a promise to produce the actual byte array when the task is complete. The await operator suspends execution until the work of the GetByteArrayAsync method is complete. In the meantime, control is returned to the caller of GetPageSizeAsync. When the task finishes execution, the await expression evaluates to a byte array.

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      string[] args = Environment.GetCommandLineArgs();
      if (args.Length > 1)
         GetPageSizeAsync(args[1]).Wait();
      else
         Console.WriteLine("Enter at least one URL on the command line.");
   }

   private static async Task GetPageSizeAsync(string url)  
   {  
       var client = new HttpClient();  
       var uri = new Uri(Uri.EscapeUriString(url));
       byte[] urlContents = await client.GetByteArrayAsync(uri);
       Console.WriteLine($"{url}: {urlContents.Length/2:N0} characters");  
   }  
}
// The following call from the command line:
//    await1 http://docs.microsoft.com
// displays output like the following: 
//   http://docs.microsoft.com: 7,967 characters


Important

For the complete example, see Walkthrough: Accessing the Web by Using Async and Await. You can download the sample from Developer Code Samples on the Microsoft website. The example is in the AsyncWalkthrough_HttpClient project.

As shown in the previous example, if await is applied to the result of a method call that returns a Task<TResult>, then the type of the await expression is TResult. If await is applied to the result of a method call that returns a Task, then the type of the await expression is void. The following example illustrates the difference.

// await keyword used with a method that returns a Task<TResult>.  
TResult result = await AsyncMethodThatReturnsTaskTResult();  

// await keyword used with a method that returns a Task.  
await AsyncMethodThatReturnsTask();  

// await keyword used with a method that returns a ValueTask<TResult>.
TResult result = await AsyncMethodThatReturnsValueTaskTResult();

An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off.

An await expression can occur only in the body of its enclosing method, lambda expression, or anonymous method, which must be marked with an async modifier. The term await serves as a keyword only in that context. Elsewhere, it is interpreted as an identifier. Within the method, lambda expression, or anonymous method, an await expression cannot occur in the body of a synchronous function, in a query expression, in the block of a lock statement, or in an unsafe context.

Exceptions

Most async methods return a Task or Task<TResult>. The properties of the returned task carry information about its status and history, such as whether the task is complete, whether the async method caused an exception or was canceled, and what the final result is. The await operator accesses those properties by calling methods on the object returned by the GetAwaiter method.

If you await a task-returning async method that causes an exception, the await operator rethrows the exception.

If you await a task-returning async method that's canceled, the await operator rethrows an OperationCanceledException.

A single task that is in a faulted state can reflect multiple exceptions. For example, the task might be the result of a call to Task.WhenAll. When you await such a task, the await operation rethrows only one of the exceptions. However, you can't predict which of the exceptions is rethrown.

For examples of error handling in async methods, see try-catch.

Example

The following example returns the total number of characters in the pages whose URLs are passed to it as command line arguments. The example calls the GetPageLengthsAsync method, which is marked with the async keyword. The GetPageLengthsAsync method in turn uses the await keyword to await calls to the HttpClient.GetStringAsync method.

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

class Example
{
   static void Main()
   {
      string[] args = Environment.GetCommandLineArgs();
      if (args.Length < 2)
         throw new ArgumentNullException("No URLs specified on the command line.");
      
      long characters = GetPageLengthsAsync(args).Result;
      Console.WriteLine($"{args.Length - 1} pages, {characters:N0} characters");
   }

   private static async Task<long> GetPageLengthsAsync(string[] args)
   {
      var client = new HttpClient();
      long pageLengths = 0;

      for (int ctr = 1; ctr < args.Length; ctr++) {
         var uri = new Uri(Uri.EscapeUriString(args[ctr]));
         string pageContents = await client.GetStringAsync(uri);
         Interlocked.Add(ref pageLengths, pageContents.Length);
      }
      return pageLengths;
   }
}

Because the use of async and await in an application entry point is not supported, we cannot apply the async attribute to the Main method, nor can we await the GetPageLengthsAsync method call. We can ensure that the Main method waits for the async operation to complete by retrieving the value of the Task<TResult>.Result property. For tasks that do not return a value, you can call the Task.Wait method.

See also

Asynchronous Programming with async and await
Walkthrough: Accessing the Web by Using Async and Await
async