Why the main does not wait until the async method has finished?

I have this console application, a reduce example of my application, but that allows to reproduce the behavior.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Start");
            addAsync01(1, 2);
        }
        catch
        {
        }
        finally
        {
            Console.WriteLine("Finally");
            Console.ReadKey();
        }
        addAsync01(1,2);
    }

    private static async void addAsync01(int sum1, int sum2)
    {
        int result = await AddAsync(sum1, sum2);
        Console.WriteLine("El resultado de sumar 1 y 2 es: " + result);
    }

    public static async Task<int> AddAsync(int num1, int num2)
    {
        return await Task<int>.Run(() =>
        {
            return num1 + num2;
        });
    }
}

In the addSyn01 method,I have used a await keyword, but the application does not wait until the method AddAsync is finished, continue running, so the result that I get in the console is:

Start
Finally
El resultado de sumar 1 y 2 es: 3

I expected this:

Start
El resultado de sumar 1 y 2 es: 3
Finally

If I am not wrong, the await keyword wait that the async method finish to continue with the next code of line.

If I use this code in the AddAsync01 method, it works as I expect:

private static async void addAsync01(int sum1, int sum2)
{
    Task<int> tskResult = AddAsync(1, 2);
    await Task.WhenAll(tskResult);

    Console.WriteLine("El resultado de sumar 1 y 2 es: " + tskResult.Result);
}

Answers


Console applications do not support async / await on the entry point of the application, as you might expect them to. You need to invoke .Wait() or (.Result for Task<T> returning methods). I would suggest looking into Stephen Cleary's Async Console Program if you're curious about why it doesn't work as you'd expect.

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Console.WriteLine("Start");

            addAsync01(1, 2).Wait();
        }
        catch
        {
            //TODO
        }
        finally
        {
            Console.WriteLine("Finally");
            Console.ReadKey();
        }
        addAsync01(1, 2).Wait();
    }

    static async Task addAsync01(int sum1, int sum2)
    {
        int result = await AddAsync(sum1, sum2);
        Console.WriteLine("El resultado de sumar 1 y 2 es: " + result);
    }

    public static async Task<int> AddAsync(int num1, int num2)
    {
        return await Task.Run(() => num1 + num2);
    }
}

Additionally, you need to return Task on the addAsync01 method.

Here is the output with the changes:

Start
El resultado de sumar 1 y 2 es: 3
Finally

While this change does work and correctly answers your question, it is odd to me that you would want to introduce asynchronous code without an obvious reason. If you're simply trying to understand how it functions, fine; however if this is desirable code you might want to reconsider the approach. The summation of two int's is not computationally expensive at all, and this could be done synchronously much faster and with less overhead.


If you want the addAsync01() method to be synchronous, don't declare it as async. When not declaring the method as async, you won't be able to use "await" inside it. So you must explicitely wait for the asynchronous method called from the synchronous method the following way:

    private static void addAsync01(int sum1, int sum2)
    {
        var lTask = AddAsync(sum1, sum2);
        lTask.Wait();
        int result = lTask.Result;

        Console.WriteLine("El resultado de sumar 1 y 2 es: " + result);
    }

Be careful when using such code inside complexer multi-threading environments. It is very easy to produce deadlocks.


Need Your Help

How to declare database connection variable globally in Swift

ios swift sqlite.swift

I need to initialize a variable to connect to an SQLite database in Swift. I am using the SQLite.swift library and need to connect to the database with this line:

AJAX call not working on jQuery toggle

javascript jquery ajax

In attempt to make my jQuery toggles more manageable; I'm trying to successfully pull it's content through an AJAX call, but my AJAX call kills my toggles -- any pointers as to what I'm doing wrong...