Previously in .NET 4.0 you had two choices for long-running or IO operations - either block the current thread until the operation completed (which causes scaling issues) or use callbacks to handle the result (had to read and debug).
.NET 5.0 introduced two new keywords used in conjunction with the Task
type to simplify asynchronous programming.
async
indicates that the declared function should allowawait
to indicate where it will return control to the caller while the task is running. It does this by returning aTask
orTask<T>
which indicates the status of the operation and any results.await
signals the function should return control to the caller when calling another async Task-based method and it will unwrap the result when it is available. It can only be used inside anasync
function.
Code
C#
// Using WebRequest for comparison to older styles
var request = WebRequest.Create("https://damieng.com");
var response = await request.GetResponseAsync().ConfigureAwait(false);
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
Console.WriteLine(reader.ReadToEnd());
// But you're better off using HttpClient, get httpClient from factory/shared instance
var response = await httpClient.GetStringAsync("https://damieng.com");
Console.WriteLine(response);
C#
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());
C#
var request = WebRequest.Create("https://damieng.com");
Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)
.ContinueWith(task =>
{
var response = (HttpWebResponse)task.Result;
using (var stream = response.GetResponseStream())
using (var reader = new StreamReader(stream))
Console.WriteLine(reader.ReadToEnd());
});
Notes
- Use
.ConfigureAwait(false)
after anyawait
when you don't need to return to the original context- This avoids unnecessary context switching and improves performance and scalability
- Do not
ConfigureAwait
in application UI code as the UI must be updated on the original context