Skip to content

Asynchronous members C# 5.0readabilitynew scenarios

Provide `async` and `await` operations to simplify Task-based operations.

Previously in .NET 4.0 you had to either block the current thread until a long-running or IO operation completed (which causes scaling issues) or handle the result in a callback or ContinueWith continuation (hard to read and debug).

C# 5.0 introduced two new keywords used in conjunction with the Task type to simplify asynchronous programming.

  • async marks a method (or lambda) that can use await. It usually returns a Task or Task<T> which represents the status of the operation and any result (async void exists for event handlers only).
  • await waits for an awaitable such as a Task and unwraps its result. If the task has not completed yet the method returns control to its caller and resumes later. It can only be used inside an async method.

Code ​

csharp
// Using WebRequest for comparison to older styles
var request = WebRequest.Create("https://damieng.com");
using (var response = await request.GetResponseAsync())
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
    Console.WriteLine(await reader.ReadToEndAsync());

// But you're better off using HttpClient, get httpClient from factory/shared instance
var html = await httpClient.GetStringAsync("https://damieng.com");
Console.WriteLine(html);
csharp
var request = WebRequest.Create("https://damieng.com");

using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream))
    Console.WriteLine(reader.ReadToEnd());
csharp
var request = WebRequest.Create("https://damieng.com");

Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)
    .ContinueWith(task =>
    {
        using (var response = task.Result)
        using (var stream = response.GetResponseStream())
        using (var reader = new StreamReader(stream))
            Console.WriteLine(reader.ReadToEnd());
    });

Notes ​

  • WebRequest is obsolete in .NET 6 and later, use HttpClient for new code
  • In library code add .ConfigureAwait(false) to each await when you don't need to resume on the original context
    • This avoids unnecessary context switching and the deadlocks that occur when callers block on the task
    • Do not use it in UI code that touches controls after the await, as the UI must be updated on the original context
    • ASP.NET Core has no synchronization context so it makes no difference there

More information ​

Powered by Intracia