0

I was going through https://blog.stephencleary.com/2012/02/async-and-await.html and according to the author the Context is either of the following:

  1. If you’re on a UI thread, then it’s a UI context.

  2. If you’re responding to an ASP.NET request, then it’s an ASP.NET request context.

  3. Otherwise, it’s usually a thread pool context.

So in a console application with the following code:

public static void Main()
{
    Thread.CurrentThread.Name = "MainThread";
    var task = SomeAsync();
    string result = task.Result;
    Console.WriteLine(result);
}

private static async Task<string> SomeAsync() {
    await Task.Delay(2000);
    return "random String";
}

Here we start an async method from the Main method. The execution of this async method will take 2 seconds and by the time it completes the control will be back in the Main method at the line where we are blocking on the result of the async method. So we can say that the MainThread is blocked waiting for the result of SomeAsync. By the time SomeAsync completes, the MainThread is still blocked.

So can I say that the continuation of the async method will be executed on a different thread from the thread pool (as this code works and prints the string correctly)? Had it been a UI application it would have resulted in a deadlock but no deadlock in case of console application. Are the console applications contextless and may use a new thread from the thread pool when the need arises?

Navjot Singh
  • 678
  • 7
  • 18
  • 1
    BTW, calling `.Result` blocks the current thread and negates the usefullness of `Task` –  May 07 '20 at 09:41
  • @MickyD I know that. I was just curious that when the current thread is blocked, where is the continuation of the async method being executed? – Navjot Singh May 07 '20 at 09:47
  • You might want to check out C# 7.1. It allows for `async Task Main()` :) –  May 07 '20 at 12:04
  • I know that as well. I wanted to know more about how the things are happening under the hood. – Navjot Singh May 07 '20 at 12:15

2 Answers2

1

Use of async in your methods does not necessarily lead to the creation of a new thread:

Does the use of async/await create a new thread?

And particularly in your case, where you are actually running this method synchronously (no await), then this will very likely run on a single thread. To truly 'test' the async functionality, you should start awaiting results and then see what happens.

Paddy
  • 33,309
  • 15
  • 79
  • 114
  • I am using a `Main` which is not async so I am blocking with the help of `Result`. I would like to know where is the continuation of the `SomeAsync` run when the `MainThread` is blocked. I know the basics of async await and I know it is a state machine. I want to know more about this particular scenario. – Navjot Singh May 07 '20 at 09:41
0

I try to show you how the async await works:

class Program
{
    static void Main(string[] args)
    {
        TestAsync().Wait(); //This will run synchronously
    }

    private static async Task TestAsync()
    {
        Log("Test started");

        Log("Application will be blocked for 5 seconds");
        await Wait5Seconds();
        Log("Now it will run again");

        var task = Wait20Seconds();
        while (!task.IsCompleted)
        {
            Log("This will be logged during method execution cause we didn't await it");
        }

        var task1 = Wait20Seconds();
        Log("We will execute this log and then we will await the end of the execution of our task");
        await task1;

        Log("Test ended");
    }

    private static async Task Wait5Seconds()
    {
        await Task.Delay(1000 * 5);
    }

    private static async Task Wait20Seconds()
    {
        await Task.Delay(1000 * 20);
        Log("DONE!");
    }

    private static void Log(string message)
    {
        Console.WriteLine(string.Format("{0} - {1}", DateTime.Now, message));
    }
}
Marco Salerno
  • 5,131
  • 2
  • 12
  • 32
  • On which thread does the line `Log("Now it will run again")` run? The main thread is blocked by the `Wait()` call because `await Wait5Seconds()` returned the control to the main method. – Navjot Singh May 07 '20 at 09:57
  • It will still run on the main thread. You are using a different thread in the Log("This will be logged during method execution cause we didn't await it"); example – Marco Salerno May 07 '20 at 10:04
  • How can it run on the main thread, isn't it blocked by the Wait() call? – Navjot Singh May 07 '20 at 10:07
  • Nope, the wait call means that the code it is referring to, will be executed in the current thread instead of needing another one – Marco Salerno May 07 '20 at 10:08
  • `Wait` will synchronously block until the task completes. So the current thread is literally blocked waiting for the task to complete. If the thread is blocked how can it be used to execute the task itself. – Navjot Singh May 07 '20 at 10:13
  • I already told you, you are misleading how it works.When people say "block" they mean it won't run other lines of code after the "wait" till it ends, so your machine will use that thread instead of needing another one – Marco Salerno May 07 '20 at 10:15
  • I still don't agree. Why does the same code will lead to deadlock in UI application? – Navjot Singh May 07 '20 at 10:20
  • Because an UI application runs differently and the UI thread is always the main thread, handling always UI. – Marco Salerno May 07 '20 at 10:23