为什么 async/await 在我的 ASP.net 5 控制台应用程序中不起作用?
Why is async/await not working in my ASP.net 5 Console Application?
我在 Windows (.NET 4.5.1) 和 Linux (Mono 4.0.1) 上尝试了这个简单的 ASP.net 5 控制台应用程序,两次都得到相同的结果.
注意: 我称它为 ASP.net 5 控制台应用程序,因为在 RC 之前的 Visual Studio 中就是这样称呼的。现在它被称为控制台应用程序(包),但它仍然使用来自 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-beta4 CLR
或 1.0.0-beta5-11904 CLR
时,命令 dnx . ConsoleApplication
不打印任何内容。程序一遇到 Task.Delay
就以状态码 0 退出。即使是 finally 块也永远不会执行。
我无法测试 .NET Core 5.0,因为 dnu restore
说一切正常,但运行时无法找到包。哦好吧...
有人对 async/await 和 DNX 有同样的问题吗?或者发现我犯的一些错误?
如果您在 中看到我的问题(和答案),您会在调用堆栈的最顶部看到以下内容:
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;
}
}
在内部,它会检查方法的return类型,如果return类型是Task
类型,那么它会注册一个ContinueWith
,这它将能够同步等待:
if (result is Task)
{
return ((Task)result).ContinueWith(t =>
{
return 0;
});
}
当您传入 async void
时,它看起来 Execute
就好像此方法是 "fire and forget" void returning 方法一样。这就是为什么它永远不会完成执行。但是,如果您将其更改为 return a 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");
}
}
我在 Windows (.NET 4.5.1) 和 Linux (Mono 4.0.1) 上尝试了这个简单的 ASP.net 5 控制台应用程序,两次都得到相同的结果.
注意: 我称它为 ASP.net 5 控制台应用程序,因为在 RC 之前的 Visual Studio 中就是这样称呼的。现在它被称为控制台应用程序(包),但它仍然使用来自 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-beta4 CLR
或 1.0.0-beta5-11904 CLR
时,命令 dnx . ConsoleApplication
不打印任何内容。程序一遇到 Task.Delay
就以状态码 0 退出。即使是 finally 块也永远不会执行。
我无法测试 .NET Core 5.0,因为 dnu restore
说一切正常,但运行时无法找到包。哦好吧...
有人对 async/await 和 DNX 有同样的问题吗?或者发现我犯的一些错误?
如果您在
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;
}
}
在内部,它会检查方法的return类型,如果return类型是Task
类型,那么它会注册一个ContinueWith
,这它将能够同步等待:
if (result is Task)
{
return ((Task)result).ContinueWith(t =>
{
return 0;
});
}
当您传入 async void
时,它看起来 Execute
就好像此方法是 "fire and forget" void returning 方法一样。这就是为什么它永远不会完成执行。但是,如果您将其更改为 return a 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");
}
}