为什么main不等到异步方法完成?

时间:2015-12-01 15:09:37

标签: c# async-await task-parallel-library

我有这个控制台应用程序,我的应用程序的缩减示例,但允许重现行为。

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;
        });
    }
}

addSyn01方法中,我使用了await关键字,但应用程序不会等到方法AddAsync完成,继续运行,因此我在控制台中得到的结果是:

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

我期待这个:

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

如果我没有错,await关键字会等待async方法完成以继续下一行代码。

如果我在AddAsync01方法中使用此代码,它可以正常工作:

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);
}

2 个答案:

答案 0 :(得分:12)

控制台应用程序不支持应用程序入口点上的async / await,正如您所期望的那样。您需要为.Wait()返回方法调用.Result或(Task<T>)。如果您对于为什么它没有像您期望的那样工作,我建议您调查一下Stephen Cleary's Async Console Program

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);
    }
}

此外,您需要在Task方法上返回addAsync01

以下是带有更改的输出:

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

虽然这种更改确实有效并且正确回答了您的问题,但我很奇怪您想要在没有明显原因的情况下引入异步代码。如果您只是想了解它的功能,那很好;但是,如果这是理想的代码,您可能需要重新考虑该方法。两个int's的总和在计算上并不昂贵,而且这可以更快地同步完成并且开销更少。

答案 1 :(得分:0)

如果您希望addAsync01()方法是同步的,请不要将其声明为异步。当不将该方法声明为异步时,您将无法在其中使用“await”。因此,您必须以下列方式明确地等待从同步方法调用的异步方法:

    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);
    }

在复杂的多线程环境中使用此类代码时要小心。生成死锁非常容易。