Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Introduction to Asynchronous Programming Model (C# 5.0 Series)

0.00/5 (No votes)
12 Nov 2010Ms-PL4 min read 15.1K  
Introduction to Asynchronous Programming Model (C# 5.0 Series)

Synchronous and Asynchronous Operations

As of today, many programs made by the software developers are running to resolve problems in a sequential way. For example, a command processor (like Windows Command Prompt) receives a user input (as a command), processes it, then outputs the result of the processing. If there is no input from the user, the command processor will keep waiting; it starts to process until a command is received; it outputs the result after processing is finished – all this happens in a special order – that is, first, wait for user input, then, server a command from user input and process; finally, return the result as the output to the user.

Let’s say the user sends a command to the processor that needs to take a certain period to serve. While the command is being processed, the user will not see any result; in other words, the user will be blocked until the processing for this command is complete, the user interface will become irresponsible; the user interface may also show a waiting cursor indicating that the command processor is busy processing the command. After finishing, the user interface will update itself to show the result from processing.

Imagine that the command processor is running in a multiuser, multitasking environment, the user may send commands to the command processor simultaneously, the user is expecting that the command processor will serve the commands in parallel; the user is also expecting that if the command processor has to take a long time to process one command from one user, and the command processor’s user interface is able to accept command from another. This means in this situation, the command processor should not block any user input, it servers the commands concurrently and each command is processed in the same order (as I said in the first paragraph).

If an operation executes to block any other operation, this operation is called a synchronous operation; otherwise, it is called an asynchronous operation.

An Example

Let’s say a Console application calculates the sum from 1 to a specified number, first the application waits for the user to input a number from Console standard input, then it calculates the sum from 1 to this number, finally the Console shows the result and then waits for another user input. Here is what the code looks like:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
 
namespace Demo
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            int number;
 
            while (true)
            {
                Console.WriteLine("Please input a number");
                number = int.Parse(Console.ReadLine());
 
                Console.WriteLine("The sum from 1 to {0} is: {1}", 
				number, Program.Sum(1, number));
            }
        }
 
        public static int Sum(int from, int to)
        {
            int result = 0;
 
            for (int i = from; i <= to; i++)
            {
                // Simulate process delay.
                Thread.Sleep(500);
                result += i;
            }
 
            return result;
        }
    }
}

When I run this program, I try to input 10 and press ENTER, the program calculates the result for 5 seconds (I put some delay logic to simulate processing time), then it prompts me to input another number again. See this screenshot.

image

But when I try to input a slightly big number, such as 100 (it is actually not a big one, but I use it to simulate the processing time), the Console returns the result after approximately 50 seconds, during the waiting time, I cannot input another number to be calculated.

So if I want to make this program highly responsible, when the program is calculating a sum from 1 to a specified number, it can also server another input number; when one calculation is complete, it immediately shows the result to me, how do I?

Well, it is the same word that converts this Sum() operation into asynchronous.

Here is the modified code in C# 5.0, note that I changed Console.WriteLine to File.AppendAllText because Console is thread synchronized, that means the Console is not used to do both WriteLine and ReadLine at the same time. I have also added comments to the code to help understand.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
 
namespace Demo
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            int number;
 
            while (true)
            {
                Console.WriteLine("Please input a number");
                number = int.Parse(Console.ReadLine());
 
                // Call the DoSum method.
                // DoSum method is marked as async so it may wait for an
                // async operation to complete then resume the control flow,
                // the async operation is specified by await keyword.
                Program.DoSum(1, number);
            }
        }
 
        public static async void DoSum(int from, int to)
        {
            // Begin wait for an async operation.
            // Note the Sum method is also an async method that takes an async operation.
            // Internally a Task object will be created and run with asynchronously.
            int result = await Program.Sum(from, to);
 
            // After await complete, resume the control flow to the calling thread
            // to continue doing other operations.
            File.AppendAllText(
                @"d:\result.txt", 
                string.Format("Sum from {0} to {1} is {2}\r\n", from, to, result));
        }
 
        public static async Task<int> Sum(int from, int to)
        {
            // Return a Task<int> object that can be awaiting.
            Task<int> sum = TaskEx.Run(() =>
            {
                int result = 0;
                for (int i = from; i <= to; i++)
                {
                    // Simulate process delay. 
                    Thread.Sleep(500); 
                    result += i;
                }
 
                return result;
            });
 
            // Wait for the sum to be calculated asynchronously.
            return await sum;
        }
    }
}

When I try to run this program again, I input numbers as shown in the following screenshot, when I input each number to the Console and press ENTER, the Console immediately prompts me to input another number:

image

And after 2 minutes, I check the text file D:\Result.txt, and the content of this file is as follows:

Sum from 1 to 10 is 55 
Sum from 1 to 20 is 210 
Sum from 1 to 40 is 820 
Sum from 1 to 50 is 1275 
Sum from 1 to 60 is 1830 
Sum from 1 to 90 is 4095 

The content shows results in an order by its calculation time.

You may have already noticed the new async and await keyword in C# 5.0. async is a contextual keyword in some place to mark a method as an async method, whose return type must be void, Task or Task<T>; await is also a contextual keyword that indicates to begin an asynchronous method invocation. await keyword requires an async method to be its expression, the return value of an await expression is null (no return type) or the instance of T of an async method whose return type is Task<T>.

Internally, async and await keywords are language syntactical sugars of C#, when compiling the code with these keywords, C# compiler emits code that using a TaskAwaiter and Task based asynchronous programming model (APM) to implement the async pattern. I will talk about it more in the coming articles of C# 5.0 series.

Conclusion

C# 5.0 will provide an easy, simple way to implement async pattern. By using the async and await keywords, the developers can take less time to implement an APM, make the code control flow more clearly and improve productivity. In the coming articles, I will discuss the new async features in C# 5.0 in detail, including the following:

  • The Task based APM
  • async methods
  • async and await keywords
  • How it works
  • Framework Class Library (FCL) async enhancements
  • Visual Studio 11.0 tooling support for async programming

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)