Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

async and await are single threaded Really?

I created following code:

using System;
using System.Threading.Tasks;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main()
       {
         Console.WriteLine("M Start");
         MyMethodAsync();
         Console.WriteLine("M end");
         Console.Read();
       }

     static async Task MyMethodAsync()
     {
        await Task.Yield();
        Task<int> longRunningTask = LongRunningOperationAsync();
        Console.WriteLine("M3");
        //and now we call await on the task 
        int result = await longRunningTask;
        //use the result 
        Console.WriteLine(result);
     }

       static async Task<int> LongRunningOperationAsync()  
      {
        await Task.Delay(1000);
        return 1;
      }
  }
}

The OutPut:

M Start
M end
M3
1

Which is fine but when I look in the Thread profiler its shows this: enter image description here And then this: enter image description here And then this: enter image description here

So it looks like I spawn threads, but from msdn says:

From Asynchronous Programming with Async and Await : Threads

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. You can use Task.Run to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available.

Am I missing or don't understanding something? Thanks.

like image 518
Dinkar Thakur Avatar asked Feb 18 '16 14:02

Dinkar Thakur


2 Answers

I explain how async and await work with threads and contexts on my blog. In summary, when await needs to wait for an asynchronous operation to complete, it will "pause" the current async method and (by default) capture a "context".

When the asynchronous operation completes, that "context" is used to resume the async method. This "context" is SynchronizationContext.Current, unless it is null, in which case it is TaskScheduler.Current. In your case, the context ends up being the thread pool context, so the rest of the async method is sent to the thread pool. If you run the same code from the UI thread, the context would be the UI context, and all the async methods will resume on the UI thread.

like image 194
Stephen Cleary Avatar answered Sep 21 '22 01:09

Stephen Cleary


The async and await keywords don't cause additional threads to be created.

Yes. It moves the CPU bound or I/O bound work to other thread from the thread pool of the process so that it is not executed on UI thread or current synchronization context, it does not create a new thread which is what meant in the MSDN description.

like image 36
Ehsan Sajjad Avatar answered Sep 21 '22 01:09

Ehsan Sajjad