await Operator Keyword in C#

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

The asynchronous method in which await is used must be 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.

The task to which the await operator is applied typically is the return value from a call to a method that implements the Task-Based Asynchronous Pattern.

The following example illustrates the use of await in an async method, WaitAsynchronouslyAsync. Contrast the behavior of that method with the behavior of WaitSynchronously. Without an await operator applied to a task, WaitSynchronously runs synchronously despite the use of the async modifier in its definition and a call to Thread.Sleep in its body.

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 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 WaitSynchronously()
{
    // Add a using directive for System.Threading.
    Thread.Sleep(10000);
    return "Finished";
}

One important point about awaitables is this: it is the type that is awaitable, not the method returning the type. In other words, you can await the result of an async method that returns Task because the method returns Task, not because it’s async. So you can also await the result of a non-async method that returns Task:

public async Task MethodAsync()
{
  // Note that this is an async method, so we can use await in here.
  await ...
}
public Task NonAsyncMethod()
{
  // Note that this is not an async method, so we can't use await in here.
  ...
}
public async Task ComposeAsync()
{
  // We can await Tasks, regardless of where they come from.
  await NewStuffAsync();
  await MyOldTaskParallelLibraryCode();
}

async Modifier Keyword in C#

The async modifier indicates that the method, lambda expression, or anonymous method that it modifies is asynchronous. Such methods are referred to as async methods.

public async Task DoSomethingAsync()
{
    // . . . .
}

If you’re new to asynchronous programming, you can find an introduction of Asynchronous Programming in .NET using C# here.

An async method provides a convenient way to do potentially long-running work without blocking the caller’s thread. The caller of an async method can resume its work without waiting for the async method to finish.

Typically, a method modified by the async keyword contains at least one await expression or statement.

string Content = await getContentTask;

The method runs synchronously until it reaches its first await expression, at which point the method is suspended until the awaited task is complete. In the meantime, control returns to the caller of the method, as the example later in this topic shows.

If a method that’s modified by an async keyword doesn’t contain an await expression or statement, the method executes synchronously. A compiler warning alerts you to any async methods that don’t contain await because that situation might indicate an error.

When async modifies a method, a lambda expression, or an anonymous method, async is a keyword. In all other contexts, async is interpreted as an identifier. This distinction makes async a contextual keyword.

private async void DownloadFileButton_Click(object sender, EventArgs e)
{
  // Since we asynchronously wait, the UI thread is not blocked by the file download.
  await DownloadFileAsync(fileNameTextBox.Text);

  // Since we resume on the UI context, we can directly access UI elements.
  resultTextBox.Text = "File downloaded!";
}

Return Types

An async method can have a return type of Task or void. The method cannot declare any ref or out parameters, although it can call methods that have such parameters.

You specify Task as the return type of an async method if the return statement of the method specifies an operand of type TResult. You use Task if no meaningful value is returned when the method is completed. That is, a call to the method returns a Task, but when the Task is completed, any await expression that’s awaiting the Task evaluates to void.

The void return type is used primarily to define event handlers, where a void return type is required. The caller of a void-returning async method can’t await it and can’t catch exceptions that the method throws.

Asynchronous Programming in .NET

“Performance” is a term that is used a lot when talking about apps, but it’s actually a pretty vague term. There are at least two aspects of performance that most people think about: app launch time and throughput. Both of these can be measured and described with actual numbers. The true test of an app, however, is end-user perception.

Asynchronous programming is a means of parallel programming in which a unit of work runs separately from the main application thread and notifies the calling thread of its completion, failure or progress. You may be wondering when you should use asynchronous programming and what are its benefits and problem points.

The main benefits one can gain from using asynchronous programming are improved application performance and responsiveness. One particularly well suited application for the asynchronous pattern is providing a responsive UI in a client application while running a computationally or resource expensive operation.

Async and Await

The async and await keywords in C# are the heart of asynchronous programming. By using those two keywords, you can use resources in the .NET Framework or the Windows Runtime to create an asynchronous method almost as easily as you create a synchronous method. Asynchronous methods that you define by using async and await are referred to as async methods.

The following example shows an async method. Almost everything in the code should look completely familiar to you.

async Task AccessTheWebAsync()
{
    HttpClient client = new HttpClient();
    Task getStringTask = client.GetStringAsync("http://www.haidermrizvi.com");
    DoIndependentWork();
    string urlContents = await getStringTask;
    return urlContents.Length;
}

GetStringAsync returns a Task. That means that when you await the task you’ll get a string (urlContents).

The await operator suspends AccessTheWebAsync.

AccessTheWebAsync can’t continue until getStringTask is complete.
Meanwhile, control returns to the caller of AccessTheWebAsync.
Control resumes here when getStringTask is complete.
The await operator then retrieves the string result from getStringTask.

The following characteristics summarize what makes the previous example an async method.

  • The method signature includes an async modifier.
  • The name of an async method, by convention, ends with an “Async” suffix.
    • The return type is one of the following types:

    • Task if your method has a return statement in which the operand has type TResult.
    • Task if your method has no return statement or has a return statement with no operand.
      • The method usually includes at least one await expression, which marks a point where the method can’t continue until the awaited asynchronous operation is complete. In the meantime, the method is suspended, and control returns to the method’s caller. The next section of this topic illustrates what happens at the suspension point.

      Summary

      The new async and await keywords enable you to provide significant user experience improvements in your apps without much effort on your part. This term does not mean multithreaded code. By default, code written with async and await is single-threaded. But threaded code works well here.