C# : Event Based Asynchronous Pattern In Parallel Computing.

In the article discussing the “Asynchronous Pattern” – C# : ASYNCHRONOUS PROGRAMMING USING BEGININVOKE AND ENDINVOKE METHODS, we saw how to use the BeingInvoke and EndInvoke methods to achieve parallel computing. However, this is not very intuitive and requires you to explicitly call the EndInvoke method to get back the result after you asynchronous call is done.

UI Updates Are Easier To Handle :

In the Event Based Asynchronous Pattern, updating the UI becomes simpler as generally there is no need to wait on the result in an explicit manner. As the name suggests, the event handler associated with the asynchronous method is called when the method execution finishes in the background. It becomes a useful pattern when you application involves a lot of notification management. Normally, if this is done on the main UI thread it would end up blocking the main program execution and the UI responsiveness would suffer.

It Is Just A Pattern :

Since the event based asynchronous pattern is just a pattern that you need to adhere to, your implementation may vary based on the coding techniques you use. It needs to be mentioned that there are certain guidelines we need to follow if we are to design a custom implementation of the event based asynchronous pattern.

Naming Convention :

The main prerequisite for a class that follows the event based asynchronous pattern is that :

  • The method required to do async operation must be suffixed with the “Async” keyword.
  • The event signifying the async method completion must be suffixed with the “Completed” keyword.
  • The async method should not return anything and have the return type set as void.

So if you have a synchronous version of a method, say – MyMethod inside a class, its async counterpart would be named as “MyMethodAsync“.

If you have worked with WinForm applications, Microsoft ships out of the box implementation of the event based asynchronous pattern for many classes. A few examples would be WebClient and the PictureBox classes.

The WebClient class has the DownloadStringAsync method along with the DownloadStringCompleted event.

public void DownloadStringAsync (Uri address);
public event System.Net.DownloadStringCompletedEventHandler DownloadStringCompleted;

As mentioned above, it is quite possible to implement your own custom implementation of the event based asynchronous pattern, but it would be complex and you would end up writing a lot of boiler plate code yourself. It may also require you to handle the context switching issues and take care of cross-thread exceptions. If it really needs to be done, it is advisable to use the BackGroundWorker and the AsyncOperationManager classes instead.

For custom implementation of the event based asynchronous pattern the primary advantage of using the AsyncOperationManager class is that it ensures that the callback handling will happen on the main thread honoring the synchronization context.

In this article we will look at a code example where you can use out of the box implementation of the event based asynchronous pattern. The following example demonstrates the usage of PictureBox class to load up an image in a synchronous as well as asynchronous manner and simultaneously doing other tasks while the image loads.

Synchronous Operation : 

For this example we have a WinForm application with 4 PictureBox controls that load different images using URLs. There are 4 labels that update the status for each PictureBox when the image finishes loading into the control. Since this would be handled in a synchronous fashion, we will update each label control during the sequential execution of code.

Look at the code below :

private void button1_Click(object sender, EventArgs e)
{
      DateTime startTime = DateTime.Now;
      pictureBox1.Load(@"http://www.techblogcity.com/wp-content/uploads/2019/04/binary-2689157_640.jpg");
      label1.Text = "Picture 1 completed";
      pictureBox2.Load(@"http://www.techblogcity.com/wp-content/uploads/2019/03/HIM.png");
      label2.Text = "Picture 2 completed";
      pictureBox3.Load(@"http://www.techblogcity.com/wp-content/uploads/2019/05/bloom-blossom-dahlia-60597.jpg");
      label3.Text = "Picture 3 completed";
      pictureBox4.Load(@"http://www.techblogcity.com/wp-content/uploads/2019/05/aerial-shot-beach-bird-s-eye-view-1433052.jpg");
      label4.Text = "Picture 4 completed";
      DateTime endTime = DateTime.Now;

      TimeSpan interval = endTime - startTime;

      label5.Text = interval.ToString();
}

This will get the job done. However, the issue here is the synchronous nature of execution that will block the UI thread till the last image finishes loading and its corresponding status label is updated. Consider a slow network connection where the imaging loading speed is poor. This will cause a lot of lag in the application response time and it will not be possible to do anything else in between.

Here is a screenshot of the final result. You will observe it took 17 seconds for the entire operation to complete and the UI thread blocked in the meantime. Additionally, since any UI updates are only possible until after the synchronous execution completes, it is not possible to view the status updates dynamically as they happen for each picture box.

Asynchronous Operation : 

Let us try to achieve the same results using the async method – LoadAsync from the PictureBox class. Since the async methods return the control to the calling code immediately and don’t return any value, the main UI thread is not blocked and the click event would complete very fast. How would we then update label control with the status values ? That is where the DownloadStringCompleted event comes in. Since the event handler for this event executes on main UI thread, it becomes possible to update the status labels with values as an when each picture box loads the image.

Here is the code :

private void PictureBox4_LoadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            label4.Text = "Picture 4 completed";
        }

        private void PictureBox3_LoadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            label3.Text = "Picture 3 completed";
        }

        private void PictureBox2_LoadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            label2.Text = "Picture 2 completed";
        }

        private void PictureBox1_LoadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            label1.Text = "Picture 1 completed";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            DateTime startTime = DateTime.Now;
            pictureBox1.LoadAsync(@"http://www.techblogcity.com/wp-content/uploads/2019/04/binary-2689157_640.jpg");
            pictureBox2.LoadAsync(@"http://www.techblogcity.com/wp-content/uploads/2019/03/HIM.png");
            pictureBox3.LoadAsync(@"http://www.techblogcity.com/wp-content/uploads/2019/05/bloom-blossom-dahlia-60597.jpg");
            pictureBox4.LoadAsync(@"http://www.techblogcity.com/wp-content/uploads/2019/05/aerial-shot-beach-bird-s-eye-view-1433052.jpg");
            DateTime endTime = DateTime.Now;

            TimeSpan interval = endTime - startTime;

            label5.Text = interval.ToString();

Each LoadAsync call for a particular PictureBox has it’s own Completed event handler where we update the UI status label.See how the pictures get incrementally loaded and the status labels are updated without blocking the UI.

You will notice that the button click event execution completed in just about a fraction of a second and finally we have all the picture boxes loaded with images.

This made the application responsive to user inputs like window resize or window movement. It is clearly evident how the asynchronous way of doing the same thing scores over the synchronous way.

Watch out for future posts on Task Based Parallel Programming which makes use of the async & await keywords.

Leave a Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.