-2

I have read a dozen articles about async/await and they all have been a great read. But in all those articles some confusions/questions weren't addressed. I have seen on this forum too (this awesome post) but I haven't got clear explanation,so I am seeking your profound knowledge on the matter.

Example

In the below example of Console App as synchronization context is not maintained the thread ID's are returned namely 1 and 5.

(A similar example with GUI would run on the same thread as synchronization context is maintained there.)

using System;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncConcept
{
    class Program
    {
        static void Main(string[] args)
        {
            AsyncMethod();
            Console.WriteLine("Main Thread: " + (int)AppDomain.GetCurrentThreadId());
            Console.ReadLine();
        }

        public static async void AsyncMethod()
        {
            await Task.Delay(TimeSpan.FromSeconds(5));
            Console.WriteLine("AsyncMethod Thread: " + (int)AppDomain.GetCurrentThreadId());
            Console.ReadLine();
        }
    }
}

Questions

When we use await keyword with let's say an I/O call or an API call, does await operation happens on Main thread only?

a) If yes, the how come the Main thread (UI thread in case of GUI) continue with remainder of the method simultaneously ?

b) If No, then it violates the No thread spawn theory of async and await.

Jason
  • 325
  • 2
  • 4
  • 12
  • 2
    A console app does not have a synchronization context. So this is entirely normal. Pretty much the reason why a console app is so different from a GUI app, there's nothing much subtle about Application.Run(). https://stackoverflow.com/q/52686862/17034 – Hans Passant Jun 23 '19 at 12:18
  • the concern here is the awaitable task continues to be on Main thread ? – Jason Jun 23 '19 at 13:46

1 Answers1

1

When we use await keyword with let's say an I/O call or an API call, does await operation happens on Main thread only?

await happens on whatever thread is running that method. In this case, AsyncMethod is invoked on the main thread, and the await happens on the main thread. If AsyncMethod was called by a UI thread, then the await would happen on the UI thread.

I think you are thinking that await somehow "runs" the asynchronous operation, but that is not at all what happens. What I mean by the await "happening" is that the await:

  1. Checks to see whether its awaitable is completed (in this case, the "awaitable" is the task returned from Task.Delay). If it has already completed, it continue executing the method synchronously.
  2. If the awaitable is not complete, await will (by default) capture the current context, and then use that to schedule the continuation of that method to run when the awaitable completes. Then the await returns.

Note that if the awaitable is not complete, then the method returns. In the normal case, it would return an incomplete task that completes when the async method completes; in this case, there is no return type so the calling code cannot easily know when the async method completes.

a) If yes, the how come the Main thread (UI thread in case of GUI) continue with remainder of the method simultaneously ?

Since the awaitable is not complete, await returns from the method. The rest of the method will run when the awaitable completes.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
  • Stephnen : So, Main/UI thread initiates `await` operation. When `awaitable` is not complete the Thread would pass on to the next line of instructions(the remainder of the method) not related to the await.But in the meantime, that incomplete await (_which certainly will be completed in some period of time_) will run on which thread ? The same thread ? – Jason Jun 24 '19 at 18:47
  • If you mean the awaitable, the technical answer is "however it's implemented." In the general case, it doesn't "run" anywhere; [there is no thread](https://blog.stephencleary.com/2013/11/there-is-no-thread.html). – Stephen Cleary Jun 24 '19 at 19:41