Writing asynchronous applications can be very complicated.

Luckily, C# 5 introduced a simplified approach, async programming with async and await. It leverages asynchronous support in the .NET Framework 4.5 and higher. Developers can write codes similar to synchronous codes, make them easy to write, debug, and maintain.

The async modifier specifies that a method, lambda expression, or anonymous method is asynchronous. An async method runs synchronously until it reaches its first await expression, at which point the method is suspended until the awaited task is complete. In the meantime, control returns to the caller of the method.

The await expression in an async method doesn’t block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method. (Sidebar: according to my exercise, the thread to run the continuation after awaited task is finished could be a different thread)

In order to understand async and await a little more, I wrote a simple exercise with async programming. The source of this exercise is at the end of this blog.

Output:
Main ThreadId: 1, start

Worker #1, ThreadId: 1, begin to process tons of data here …
Worker #2, ThreadId: 1, begin to process tons of data here …
Main ThreadId: 1, control back (UI responsive).

Worker #2, ThreadId: 4, finished
Worker #1, ThreadId: 5, finished

As we can see,

  1. The main thread ID was #1
  2. The main thread kicked off the workers
  3. The worker #1 and #2 used thread ID #1 until this line ‘await Task.Delay(4000);’
  4. ‘await Task.Delay(4000);’ suspended its progress and to yield control back to main thread
  5. The main thread got control back, UI was responsive, and printed out ‘Main ThreadId: 1, control back (UI responsive).’
  6. After a while, workers finished and printed the messages to indicate it’s done
  7. The thread IDs of workers after await operations were different from the main thread ID.

Item #7, this seems to contradict the documentation [1], as quoted, “The async and await keywords don’t cause additional threads to be created. Async methods don’t require multithreading because an async method doesn’t run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active.”

 

References

  1. Asynchronous programming with async and await (Excellent tutorial! Detailed explanation on what happens in an async method)
  2. Asynchronous programming
  3. async

 

Source

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main ThreadId: " 
                + Thread.CurrentThread.ManagedThreadId + ", start" + "\r\n");
            
            for (int i = 1; i <= 2; i++)
            {
                new AsyncAwait().ExecuteMethodAsync(i);
            }

            Console.WriteLine("Main ThreadId: " 
                + Thread.CurrentThread.ManagedThreadId 
                + ", control back (UI responsive)." + "\r\n");
            Console.ReadKey();
        }
    }

    public class AsyncAwait
    {             
        public async Task ExecuteMethodAsync(int workerNumber)
        {
            Console.WriteLine("Worker #" + workerNumber + ", ThreadId: " 
                + Thread.CurrentThread.ManagedThreadId
                + ", begin to process tons of data here ... ");
            await Task.Delay(4000);            
            Console.WriteLine("Worker #" + workerNumber + ", ThreadId: " 
                + Thread.CurrentThread.ManagedThreadId + ", finished");
        }
    }
Advertisements