控制台应用程序和异步等待示例被阻止

时间:2019-03-01 03:31:14

标签: c# async-await

以下示例为何被阻止?我原以为“首先运行”会立即运行,然后5秒钟后会出现“最后运行”。

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...
        }
    }
}

2 个答案:

答案 0 :(得分:5)

您正在等待(松散使用该术语)任务。

如果您不使用.GetAwaiter().GetResult();(无论如何都是内部框架方法)而只是编写

,这将更有意义。
SomeAsyncCode().Wait();
Console.WriteLine("Run First");

然后事情就变得很明显了,您正在等待任务完成。

以下内容可能更符合您的期望;

// start task
var task = SomeAsyncCode();

Console.WriteLine("Run First");

task.Wait();

但是,老实说,很少需要使用Wait方法调用ResultGetAwaiter().GetResult()async,而在中进行调用UI 应用程序或带有 Synchronization Context 的内容可能会导致死锁

理想情况下,您让asyncawait C#7.1 及更高版本中传播,您可以创建async 入口点,您可以更简洁地使用异步和等待模式

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

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

答案 1 :(得分:1)

定义async Task Method()时-告诉您应该等待此方法,即使它不会返回任何内容。

定义async void Method()时-告诉您这是 fire'n'forget 方法,您不想等待它。

此外,当void Main(string[] args)返回时-您的应用程序正在关闭,GC将终止所有任务。

因此,您的代码应更像这样:

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...
}