Click here to Skip to main content
15,881,139 members
Articles / Programming Languages / C#

How to Convert Your Old Sequential Code in to async

Rate me:
Please Sign up or sign in to vote.
4.75/5 (4 votes)
18 Oct 2012CPOL3 min read 30K   12   5
How to convert your old sequential code in to async

There are plenty of ansyc samples over the internet, and most of them are different and do not satisfy your requirements. Actually, async pattern depends on its creator, and can be implemented in various ways. It is important to understand the async pattern in order to use it. Only in this way, you can stop searching for the exact sample you need, and start coding your own async code. More than a year ago, I wrote a simple blog post about async pattern (part 1 and part 2) (Bosnian language), and also wrote how to call Entity Framework with async pattern as well.

Today, I am going to show you how old synchronous code block converts into asynchronous. I think it is interesting because async pattern can improve your existing applications in various ways. First of all, async pattern can increase the responsiveness of an application, performance, etc.

First of all, create a simple Windows Forms sample and implement synchronous code. This will represent our old application, in which we are going to implement a new programming paradigm.

  1. Create Windows Forms Project, Name it “WinFormsAsyncSample”.

    Image 1

  2. Design your main form (Form1.cs) exactly as the picture shows below, and implement events.

    Image 2

    As the picture shows, we have few labels, one text box, one progress bars, and two buttons.

Note: At the end of the blog, you can download both versions (nonasync and async) of this sample.

The sample application calculates how many prime numbers exist in range. You need to enter number, press run button. The program starts counting. The progress bars inform the user status of counting.

Let's see the implementation of runBtn_Click event:

C#
private void btnRun_Click(object sender, EventArgs e)
{
    if(!int.TryParse(textBox1.Text,out m_number))
        m_number= 1000000;

    textBox1.Text = m_number.ToString();
    progressBar1.Maximum = m_number;
    progressBar1.Minimum = 0;
    progressBar1.Value = 0;

    //call start calculation
    startCounting();
}

At the beginning of the btnRun_Click, we prepare progressBar, and also convert text from textbox into int type. At the end of the function, startCounting method is called. Here is the source code of the method:

C#
private void startCounting()
{
    int counter=0;
    for(int i=2; i< m_number; i++)
    {
        bool retVal= IsPrime(i);
        progressBar1.Value++;
        if (retVal)
        {
            counter++;
            label3.Text = "Result is: " + counter.ToString();
        }
    }
}

The method is very simple. It iterates from 2 to specified number by calling helper method IsPrime (see the source code of the blog post) to check if a certain number is prime. Then the method increased the counter variable and tried to update label about current count value. If you run the sample and press run button, you can see that the application is not responsive on user input, and represents classic sequential, synchronous single thread application.

Now I am going to show how this implementation can be converted into async with minimum code changes. We are going to change only startCounting method, other code will remain the same. Explanation is divided in only 3 steps, which is enough to convert our code into full async pattern.

  • Put async keyword right after public modifier of startCounting method.

Explanation: Every method which implements async patter needs to be decorated with async.

  • Put sequential implementation in to Task action, and wait.

Explanation: With this, you define a Task object which will run the code without blocking the main thread. The simplest implementation is the following:

C#
private async void startCalculation()
{
    var task = new Task(() =&gt;
        {
            int counter = 0;
            for (int i = 2; i < m_number; i++)
            {
                bool retVal = IsPrime(i);

                this.Invoke((Action)(()=>
                {
                    progressBar1.Value++;
                    if (retVal)
                    {
                        counter++;
                        label3.Text = "Result is: " + counter.ToString();
                    }

                }));
            }
        });

    task.Start();
    await task;
}

Now if you run the sample, you have fully asynchronous implementation. Main thread is free and can receive user input. So this is the simplest way how to convert your sync code in to async. This is the case when Task object creates another thread in order to execute the code. That’s why we called this.Invoke method in order to set controls properties progressBar.Value and label3.Text. Everything else remain the same as in the previous implementation.

  • Create global variable of type CancellationTokenSource and call Cancel method from Cancel Event handler.

Explanation: In this way, we can cancel counting at any time. With this case, we need to implement extra code in our previous implementation like the following:

C#
private async void RunProces()
{
    if (m_IsRunning)
        return;
    m_IsRunning = true;
    int counter=0;
    if (m_ct != null)
    {
        m_ct.Dispose();
        m_ct = null;
    }
    m_ct = new CancellationTokenSource();

    var task = new Task(() =>
        {
            for (int i = 0; i < m_number; i++)
            {
                bool retVal = IsPrime(i);

                this.Invoke((Action)(()=>
                {
                    progressBar1.Value++;
                    if (retVal)
                    {
                        counter++;
                        label3.Text = "Result is: " + counter.ToString();
                    }

                }));

                if (m_ct.IsCancellationRequested)
                {
                    m_IsRunning = false;
                    return;
                }
            }
        }, m_ct.Token);

    task.Start();
    await task;
}

With the last code implementation, you have full of async patter in your old application.

In this blog post, I have tried to explain as simply as possible the way in which you can convert your old sync code into new async programming pattern.

The source code sample used in this blog post:

  • In this link, you can find sequential version of the sample.
  • In this link, you can find the final solution of async pattern.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Bosnia and Herzegovina Bosnia and Herzegovina
Bahrudin Hrnjica holds a Ph.D. degree in Technical Science/Engineering from University in Bihać.
Besides teaching at University, he is in the software industry for more than two decades, focusing on development technologies e.g. .NET, Visual Studio, Desktop/Web/Cloud solutions.

He works on the development and application of different ML algorithms. In the development of ML-oriented solutions and modeling, he has more than 10 years of experience. His field of interest is also the development of predictive models with the ML.NET and Keras, but also actively develop two ML-based .NET open source projects: GPdotNET-genetic programming tool and ANNdotNET - deep learning tool on .NET platform. He works in multidisciplinary teams with the mission of optimizing and selecting the ML algorithms to build ML models.

He is the author of several books, and many online articles, writes a blog at http://bhrnjica.net, regularly holds lectures at local and regional conferences, User groups and Code Camp gatherings, and is also the founder of the Bihac Developer Meetup Group. Microsoft recognizes his work and awarded him with the prestigious Microsoft MVP title for the first time in 2011, which he still holds today.

Comments and Discussions

 
QuestionNope - you are not meant o return void from Pin
TRexius13-Aug-13 21:12
TRexius13-Aug-13 21:12 
AnswerRe: Nope - you are not meant o return void from Pin
Bahrudin Hrnjica14-Aug-13 7:44
professionalBahrudin Hrnjica14-Aug-13 7:44 
Hi Thanks for comment and additional information which is very valuable.

In the article I have tried to describe this subject as simple as posible without involving reader in to the TAP pattern and advanced stuff around async void.
GeneralMy vote of 4 Pin
rahman_tanzilur0113-Jan-13 11:00
rahman_tanzilur0113-Jan-13 11:00 
GeneralMy vote of 5 Pin
member6019-Oct-12 1:09
member6019-Oct-12 1:09 
GeneralRe: My vote of 5 Pin
Bahrudin Hrnjica29-Nov-12 3:31
professionalBahrudin Hrnjica29-Nov-12 3:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.