Rod
Rod

Reputation: 15457

console application and async await example is blocking

Why is the following example blocking? I was expecting "Run First" to run immediately and then 5 seconds later the "Run Last" would appear.

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // Call SomeAsyncCode() somehow
            SomeAsyncCode().GetAwaiter().GetResult();

            Console.WriteLine("Run First");
        }

        private static async Task SomeAsyncCode()
        {
            // Use await here!
            await Task.Delay(5000);

            Console.WriteLine("Run Last");
            // Other async goodness...
        }
    }
}

Upvotes: 1

Views: 641

Answers (2)

TheGeneral
TheGeneral

Reputation: 81493

You are awaiting (term used loosely) the task.

It would make more sense if you didn't use .GetAwaiter().GetResult(); (which are internal framework methods anyway) and just wrote

SomeAsyncCode().Wait();
Console.WriteLine("Run First");

It then becomes obvious whats happening, you are waiting for the task to complete.

The following is probably more like what you expect;

// start task
var task = SomeAsyncCode();

Console.WriteLine("Run First");

task.Wait();

In all honesty though, it should be rare to need to call, Wait, Result or GetAwaiter().GetResult() on an async method, doing so in a UI app, or something with a Synchronization Context will likely cause a deadlock

Ideally you let async and await propagate, in C# 7.1 and higher you have the ability to create an async Entry Point which allows you use the Async and Await Pattern in a more succinct manner

static async Task Main(string[] args)
{
    await SomeAsyncCode();
    Console.WriteLine("Run First");
}

or

static async Task Main(string[] args)
{     
    var task = SomeAsyncCode();
    Console.WriteLine("Run First");
    await Task.WhenAll(task);
}

Upvotes: 5

vasily.sib
vasily.sib

Reputation: 4002

When you define async Task Method() - you are telling that this method should be awaited even though it will return nothing.

When you define async void Method() - you are telling that this is fire'n'forget method and you don't want to await it.

Also, when you void Main(string[] args) is returning - your application is closing and GC will kill all your tasks.

So, your code should be more like this:

static void Main(string[] args)
{
    // Call SomeAsyncCode() somehow
    SomeAsyncCode();

    Console.WriteLine("Run First");
    Console.ReadKey(); // you need this to prevent app from closing
}

private static async void SomeAsyncCode()
{
    // Use await here!
    await Task.Delay(5000);

    Console.WriteLine("Run Last");
    // Other async goodness...
}

Upvotes: 1

Related Questions