IWebHost:调用Run()vs RunAsync()

Ali*_*hid 18 c# asp.net-core asp.net-core-2.0 c#-7.1

创建新的ASP.NET Core 2.0项目时,类中的样板Main方法Program如下所示:

public static void Main(string[] args)
{
    BuildWebHost(args).Run(); // BuildWebHost returns an IWebHost
}
Run Code Online (Sandbox Code Playgroud)

但是从C#7.1开始,该Main方法可以是一个返回的异步方法Task而不是void.这意味着在内部调用异步方法要容易得多Main.

因此可以在内部调用RunAsync()on 而不是方法.像这样的东西:IWebHostMainRun()

public static async Task Main(string[] args)
{
    await BuildWebHost(args).RunAsync().ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

根据文档,Run方法:

运行Web应用程序并阻止调用线程,直到主机关闭.

RunAsync方法:

运行Web应用程序并返回仅在触发令牌或触发关闭时才完成的任务.

我想知道何时应该使用该RunAsync方法而不是常规Run方法?这有什么实际意义?最终用户会注意到任何差异吗?

pok*_*oke 15

默认的ASP.NET Core模板包含以下Main方法:

public static void Main(string[] args)
{
    BuildWebHost(args).Run();
}
Run Code Online (Sandbox Code Playgroud)

那个Run方法有WebHostExtensions.Run扩展方法,它实现如下:

public static void Run(this IWebHost host)
{
    host.RunAsync().GetAwaiter().GetResult();
}
Run Code Online (Sandbox Code Playgroud)

所以这实际上是调用WebHostExtensions.RunAsync,只是阻塞它.


现在,让我们看看如何指定 C#7.1的异步Main方法:

当[这些基于任务的方法]之一被识别为入口点时,编译器将合成一个实际入口点方法,该方法调用以下编码方法之一:

  • static Task Main() 将导致编译器发出相当于的 private static void $GeneratedMain() => Main().GetAwaiter().GetResult();
  • static Task Main(string[]) 将导致编译器发出相当于的 private static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();

所以基本上,有这样的异步Main方法:

public static async Task Main(string[] args)
{
    await BuildWebHost(args).RunAsync();
}
Run Code Online (Sandbox Code Playgroud)

会导致编译器还发出以下内容:

private static void $GeneratedMain(string[] args)
{
    Main(args).GetAwaiter().GetResult();
}
Run Code Online (Sandbox Code Playgroud)

如果你仔细观察那里返回的任务会发生什么,这与WebHostExtensions.Run方法的作用完全相同.

那么这是什么意思?您可以使用这些解决方案中的任何一种,效果也是一样的.您的应用程序将正确阻止,直到异步任务得到解决.解决方案之间没有实际差异.使用异步主方法的唯一真正好处是,如果您在方法中有其他异步工作要做Main; 虽然这可能是非常罕见的情况,因为对于Web应用程序,您更有可能在ASP.NET Core应用程序的生命周期内进行设置工作(即在其中Startup,而不是在其外部).


idu*_*ori 10

这有什么实际意义?最终用户会注意到任何差异吗?

运行时级别的行为没有差异。

由于此功能不对应于 CLR 代码更改,因此async Main 方法只是一个语法糖。这种设计允许后端与该语言的早期版本兼容。要了解更多详细信息,请参阅 Roslyn Git 存储库中的 Async Main。
- C# 7 系列,第 2 部分:异步主函数