Connect with us


404: Not discovered

The async and await key phrases had been launched in C# to make asynchronous programming on the .NET platform simpler. These key phrases have essentially modified how code is written in a lot of the C# ecosystem. Asynchronous programming has grow to be mainstream, and trendy frameworks reminiscent of ASP.NET Core are totally asynchronous.

Having such an influence on the C# ecosystem, asynchronous programming proves to be fairly useful. However what’s asynchronous programming within the first place?

This text goes to introduce asynchronous programming, present utilization of async and await key phrases, discuss concerning the impasse pitfall and end with some ideas for refactoring blocking C# code with these key phrases.

Let’s begin with terminology.

Concurrent vs Parallel vs Asynchronous

What are the variations between these three phrases? All of them are purposes of multi-threading, their definitions overlap, and they’re usually used interchangeably. That’s why the terminology for implementations that leverage multi-threading could be complicated.

We’ll undergo the nuances between these phrases, in order that we will provide you with a transparent definition for asynchronous programming.

Let’s assume a GUI software for instance.

Synchronous execution: doing issues one after the opposite

The person clicks a button and waits for the appliance to complete dealing with the clicking occasion. Since just one factor can occur at a time, the UI stops responding till the occasion has been utterly dealt with. In the identical manner, the appliance can’t do something within the background whereas UI is on the market for person enter.

Concurrent: doing a number of issues on the identical time

The person clicks a button, and the appliance triggers a separate thread within the background to execute the duty wanted to fulfill person’s request concurrently. The thread liable for dealing with UI occasions turns into accessible once more instantly after beginning the background thread, maintaining the UI responsive.

Parallel: doing a number of copies of one thing on the identical time

The person instructs the appliance to course of all of the information in a folder. The applying triggers a variety of threads with the processing logic and distributes the information amongst these threads.

Asynchronous: not having to attend for one job to complete earlier than beginning one other

The applying begins a database question asynchronously. Whereas the question is in progress, it additionally begins studying a file asynchronously. Whereas each duties are in progress, it does some calculation.
When all these duties are completed, it makes use of the outcomes of all these three operations to replace the UI.

Asynchronous Programming

Based mostly on the terminology above, we will outline asynchronous programming merely as follows:

The execution thread shouldn’t await an I/O-bound or CPU-bound job to complete.

Examples of I/O-bound operations could be file system entry, DB entry, or an HTTP request. Examples of CPU-bound operations could be resizing a picture, changing a doc, or encrypting/decrypting knowledge.


Utilizing asynchronous programming has a number of advantages:

  • avoiding thread pool hunger by “pausing” execution and releasing the thread again to string pool throughout asynchronous actions
  • maintaining the UI responsive
  • doable efficiency good points from concurrency

Asynchronous Programming Patterns

.NET supplies three patterns for performing asynchronous operations.

Asynchronous programming mannequin (APM): LEGACY

Often known as an IAsyncResult sample, it’s applied through the use of two strategies: BeginOperationName and EndOperationName.

public class MyClass { 
    public IAsyncResult BeginRead(byte [] buffer, int offset, int rely, AsyncCallback callback, object state) {...};
    public int EndRead(IAsyncResult asyncResult);

From the Microsoft documentation:

After calling BeginOperationName, an software can proceed executing directions on the calling thread whereas the asynchronous operation takes place on a distinct thread. For every name to BeginOperationName, the appliance also needs to name EndOperationName to get the outcomes of the operation.

Occasion-based asynchronous sample (EAP): LEGACY

This sample is applied by writing an OperationNameAsync methodology and an OperationNameCompleted occasion:

public class MyClass { 
    public void ReadAsync(byte [] buffer, int offset, int rely) {...};
    public occasion ReadCompletedEventHandler ReadCompleted;

The asynchronous operation might be began with the async methodology, which can set off the Accomplished occasion for making the outcome accessible when the async operation is accomplished. A category that makes use of EAP might also include an OperationNameAsyncCancel methodology to cancel an ongoing asynchronous operation.

Now we have solely an OperationNameAsync methodology that returns a Process or a generic Process<T> object:

public class MyClass { 
    public Process<int> ReadAsync(byte [] buffer, int offset, int rely) {...};

Process and Process<T> courses mannequin asynchronous operations in TAP. It’s vital to know Process and Process<T> courses for understanding TAP, which is vital for understanding and utilizing async/await key phrases, so let’s discuss these two courses in additional element.

Process and Process<T>

The Process and Process<T> courses are the core of asynchronous programming in .NET. They facilitate all types of interactions with the asynchronous operation they characterize, reminiscent of:

  • including continuation duties
  • blocking the present thread to attend till the duty is accomplished
  • signaling cancellation (by way of CancellationTokens)

After beginning an asynchronous operation and getting a Process or Process<T> object, you’ll be able to maintain utilizing the present execution thread to asynchronously execute different directions that don’t want the results of the duty, or work together with the duty as wanted.

Right here’s some instance code that makes use of duties to visualise what it seems like in motion:

utilizing System;
utilizing System.Threading.Duties;

public class Instance {
    public static void Major() {
       Process<DataType> getDataTask = Process.Manufacturing unit.StartNew(() => { return GetData(); } );
       Process<ProcessedDataType> processDataTask = getDataTask.ContinueWith((knowledge) => { return ProcessData(knowledge);} );
       Process saveDataTask = processDataTask.ContinueWith((pData) => { SaveData(pData)} );
       Process<string> displayDataTask = processDataTask.ContinueWith((pData) => { return CreateDisplayString(pData); } );
       Console.WriteLine(displayDataTask.End result);

Let’s stroll via the code:

  • We need to get some knowledge. We use Process.Manufacturing unit.StartNew() to create a job that instantly begins working. This job runs GetData() methodology asynchronously and, when completed, it assigns the information to its .End result property. We assign this job object to getDataTask variable.
  • We need to course of the information that GetData() methodology will present. Calling .ContinueWith() methodology, we asynchronously create one other job and set it as a continuation to getDataTask. This second job will take the .End result of the primary job as an enter parameter (knowledge) and name the ProcessData() methodology with it asynchronously. When completed, it’ll assign the processed knowledge to its .End result property. We assign this job to the processDataTask variable. (It’s vital to notice that, in the mean time, we don’t know whether or not getDataTask is completed or not, and we don’t care. We simply know what we need to occur when it’s completed, and we write the code for that.)
  • We need to save the processed knowledge. We use the identical method to create a 3rd job that can name SaveData() asynchronously when knowledge processing is completed, and set it as a continuation to processDataTask.
  • We additionally need to show the processed knowledge. We don’t have to attend for the information to be saved earlier than displaying it, so we create a fourth job that can create the show string from the processed knowledge asynchronously when knowledge processing is completed, and set it additionally as a continuation to processDataTask. (Now we’ve two duties which can be assigned as continuations to processDataTask. These duties will begin concurrently as quickly as processDataTask is accomplished.)
  • We need to print the show string to the console. We name Console.WriteLine() with .End result property of the displayDataTask. The .End result property entry is a blocking operation; our execution thread will block till displayDataTask is accomplished.
  • We need to make it possible for the information is saved earlier than leaving the Major() methodology and exiting this system. At this level, although, we have no idea the state of saveDataTask. We name the .Wait() methodology to block our execution thread till saveDataTask completes.

Nearly Good

As demonstrated above, TAP and Process/Process<T> courses are fairly highly effective for making use of asynchronous programming methods. However there’s nonetheless room for enchancment:

  • Boilerplate code wanted for utilizing duties is kind of verbose.
  • Assigning continuations and making granular choices about which job ought to run means loads of particulars needs to be dealt with by the programmer, growing the complexity and making the code error-prone. (Verbosity, mixed with elevated complexity, means the code might be obscure, thus troublesome to take care of.)
  • Regardless of all this energy, there’s no method to await a job to finish with out blocking the execution thread.

These drawbacks can grow to be vital challenges for groups to undertake TAP.

That is the place the async and await key phrases come into play.

Proceed studying
Asynchronous Programming Utilizing Async/Await in C#
on SitePoint.

Click to comment

Leave a Reply

Your email address will not be published. Required fields are marked *