为什么async/await不能在我的ASP.net 5控制台应用程序中工作

本文关键字:net 控制台 应用程序 工作 ASP 我的 async await 不能 为什么 | 更新日期: 2023-09-27 17:51:01

我在两个Windows上尝试了这个简单的ASP.net 5控制台应用程序。. NET 4.5.1)和Linux (Mono 4.0.1),两次都得到相同的结果。

注意:我称它为ASP.net 5控制台应用程序,因为在Visual Studio中直到RC都是这样称呼它的。现在它被称为控制台应用程序(包),但它仍然使用来自https://github.com/aspnet/dnx的DNX:)

My Program.cs:

using System;
using System.Threading.Tasks;
namespace ConsoleApplication
{
    public class Program
    {
        public async void Main(String[] args)
        {
            #if DNX451
            AppDomain.CurrentDomain.UnhandledException += 
                (s, e) => Console.WriteLine(e);
            #endif
            try
            {
                await Task.Delay(1000);
                Console.WriteLine("After Task.Delay");
            }
            finally
            {
                Console.WriteLine("Inside Finally");
            }
        }
    }
}

My project.json:

{
    "version": "1.0.0-*",
    "dependencies": {},
    "commands": {
        "ConsoleApplication": "ConsoleApplication"
    },
    "frameworks": {
        "dnx451": {}
    }
}

当使用1.0.0-beta4 CLR1.0.0-beta5-11904 CLR运行时,dnx . ConsoleApplication命令不打印任何内容。一旦遇到Task.Delay,程序就以状态码0退出。甚至finally块也不会被执行。

我无法测试。net Core 5.0,因为dnu restore说一切正常,但运行时无法找到包。哦…

是否有人有同样的问题与async/await和DNX?或者发现我犯的错误?

为什么async/await不能在我的ASP.net 5控制台应用程序中工作

如果你在入口点看到我的问题(和答案),可以用'async'CoreCLR上的修饰符?,您将看到在调用堆栈的最顶层,有以下内容:

public static int Execute(string[] args)
{
    // If we're a console host then print exceptions to stderr
    var printExceptionsToStdError = Environment
                                    .GetEnvironmentVariable
                                     (EnvironmentNames.ConsoleHost) == "1";
    try
    {
        return ExecuteAsync(args).GetAwaiter().GetResult();
    }
    catch (Exception ex)
    {
        if (printExceptionsToStdError)
        {
            PrintErrors(ex);
            return 1;
        }
        throw;
    }
}

在内部,它检查方法的返回类型,如果返回类型是Task,那么它注册一个ContinueWith,它将能够同步等待:

if (result is Task)
{
    return ((Task)result).ContinueWith(t =>
    {
        return 0;
    });
}

当你传入async void时,它看起来Execute好像这个方法是一个"触发并忘记"的void返回方法。这就是为什么它永远不会完成执行。但是,如果您将其更改为返回Task,它将工作:

public async Task Main(String[] args)
{
    #if DNX451
    AppDomain.CurrentDomain.UnhandledException += 
        (s, e) => Console.WriteLine(e);
    #endif
    try
    {
        await Task.Delay(1000);
        Console.WriteLine("After Task.Delay");
    }
    finally
    {
        Console.WriteLine("Inside Finally");
    }
}