首页 > 解决方案 > 当我的 .NET 代码返回一个任务时,它并没有达到预期的结果。将其更改为异步/等待,修复它。为什么?

问题描述

我有一些典型的 .NET Core 2+ 的标准代码program.cs。我主要是设置日志记录。

使用下面的代码,它不是async/await,并且会发生以下情况:

这部分是由于 Serilog 的工作原理,但这并不是真正重要的一点,AFAIK。

代码直接跳过了return CreateWebHostBuilder(args).Build().RunAsync();..当我认为这是awaited调用者所在的部分时?当我调试我的应用程序时,它确实在该行等待(挂起)......直到应用程序完成启动。一旦它准备好接受连接,它就会返回这里......并运行 .. 这意味着它调用Log.CloseAndFlush()然后return Task.CompletedTask.

越野车代码:

public static Task Main(string[] args)
{
    Log.Logger = new LoggerConfiguration()....CreateLogger();

    try
    {
        // awaits here until the app has 100% started, then continues.
        return CreateWebHostBuilder(args).Build().RunAsync();
    }
    catch (Exception exception)
    {
        Log.Logger.Fatal(exception, "Host terminated unexpectantly. Sadness :~(");
    }
    finally
    {
        // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
        Log.CloseAndFlush();
    }

    return Task.CompletedTask;
}

现在改变它来async/await修复一切。代码确实在 .. 上正确等待return CreateWebHostBuilder(args).Build().RunAsync();,然后CloseAndFlush()在应用程序关闭/终止时调用。

    public static async Task Main<T>(string[] args) where T : class
    {
        Log.Logger = new LoggerConfiguration()....CreateLogger();

        try
        {
            // Correctly waits here until the app explodes or ctrl-c has been pressed.
            await CreateWebHostBuilder<T>(args).Build().RunAsync();
        }
        catch (Exception exception)
        {
            Log.Error(exception, "Stopped program because of an exception.");
        }

        Log.Debug("Finished shutting down app.");

        // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
        Log.CloseAndFlush();
    }

如果方法只在其中做一个 async/await并且这是方法中的最后一件事,返回 Task 可能只适合吗?

标签: c#.netasynchronousasync-await

解决方案


如果该方法只在其中执行一个异步/等待并且这是该方法中的最后一件事,那么返回一个任务可能只适合吗?

基本上,是的。在您的第一个片段中返回任务将使 finally 块在您离开范围时运行,就像 try 中带有关联 finally 的任何其他 return 语句一样。正如 ckuri 所评论的那样,您的 catch 块也不会执行您想要的操作,因为它不会从任务中捕获异常,而只会从设置CreateWebHostBuilder本身中捕获异常。


推荐阅读