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

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

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

我的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"); } } } } 

我的project.json

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

当使用1.0.0-beta5-11904 CLR1.0.0-beta5-11904 CLR ,命令dnx . ConsoleApplication dnx . ConsoleApplication什么都不打印。 一旦遇到Task.Delay ,程序就会以状态码0退出。 即使是finally块也永远不会执行。

我无法测试.NET Core 5.0,因为dnu restore表示一切正常,但运行时无法找到包。 那好吧…

有没有人对async / await和DNX有同样的问题? 或者发现我犯的一些错误?

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

 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 ,就好像这个方法是“fire and forget”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"); } }