为什么 IHostedService 是异步的
Why IHostedService is async
我知道这是一个设计问题,但我试图理解它以便以最佳方式使用它。因此,请将此问题视为对如何发挥其最大功能的澄清。
为什么没有设计基于KISS的synchronized而有async的方法(StartAsync
, StopAsync
), AFAIK, web请求中Async的主要好处是让一些空闲线程被释放用于为进一步的请求提供服务,但 IHostedService
不是这种情况,因为没有请求的概念,并且总是有一个 运行(或挂起的)线程。
让我们进入兔子洞。
IHostedService
的实例由 HostedServiceExecutor.StartAsync()
调用,它是异步的 (HostedServiceExecutor source code)。
HostedServiceExecutor.StartAsync()
由 WebHost.StartAsync()
调用,它是异步的 (WebHost source code)。
WebHost
实现了 IWebHost
,它具有同步和异步两种启动版本:Start
和 StartAsync
。但是 WebHost.Start()
实现只调用异步版本:
public void Start()
{
StartAsync().GetAwaiter().GetResult();
}
最后 WebHost.Start()
被 Program.Main
调用(默认生成 ASP.NET 核心项目模板):
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
有了这个调用链,我们可以继续你的问题 "Why IHostedService
is async?" 并得到 "Why IWebHost
is async?" 或 "Why c# 7 introduced async Main()
method?".
您可以从以下讨论中得到推理:
嗯,主要原因是为了简化从程序根目录调用异步方法。通常程序流需要调用异步方法(您自己的实现或第 3 方库)。
使用旧方法,我们要做这样的事情:
public static void Main(string[] args)
{
SomeAsyncCall().GetAwaiter().GetResult();
}
但现在我们可以以一种干净的方式让它一直异步:
static async Task Main(string[] args)
{
await SomeAsyncCall();
}
IHostedService.StartAsync()
也是如此。它可能需要在主机服务准备期间调用一些异步操作。 This discussion of host services concept 对此有明确的表述:
The StartAsync method is asynchronous because we may need to execute
some preparation tasks for the job that may fail to execute and
compromise the initialization.
希望这能回答您的问题。
如果您正在寻找有关正确实施 IHostedService
的文档,这里有一个很好的文档:Implementing IHostedService in ASP.NET Core 2.0
我知道这是一个设计问题,但我试图理解它以便以最佳方式使用它。因此,请将此问题视为对如何发挥其最大功能的澄清。
为什么没有设计基于KISS的synchronized而有async的方法(StartAsync
, StopAsync
), AFAIK, web请求中Async的主要好处是让一些空闲线程被释放用于为进一步的请求提供服务,但 IHostedService
不是这种情况,因为没有请求的概念,并且总是有一个 运行(或挂起的)线程。
让我们进入兔子洞。
IHostedService
的实例由 HostedServiceExecutor.StartAsync()
调用,它是异步的 (HostedServiceExecutor source code)。
HostedServiceExecutor.StartAsync()
由 WebHost.StartAsync()
调用,它是异步的 (WebHost source code)。
WebHost
实现了 IWebHost
,它具有同步和异步两种启动版本:Start
和 StartAsync
。但是 WebHost.Start()
实现只调用异步版本:
public void Start()
{
StartAsync().GetAwaiter().GetResult();
}
最后 WebHost.Start()
被 Program.Main
调用(默认生成 ASP.NET 核心项目模板):
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
有了这个调用链,我们可以继续你的问题 "Why IHostedService
is async?" 并得到 "Why IWebHost
is async?" 或 "Why c# 7 introduced async Main()
method?".
您可以从以下讨论中得到推理:
嗯,主要原因是为了简化从程序根目录调用异步方法。通常程序流需要调用异步方法(您自己的实现或第 3 方库)。 使用旧方法,我们要做这样的事情:
public static void Main(string[] args)
{
SomeAsyncCall().GetAwaiter().GetResult();
}
但现在我们可以以一种干净的方式让它一直异步:
static async Task Main(string[] args)
{
await SomeAsyncCall();
}
IHostedService.StartAsync()
也是如此。它可能需要在主机服务准备期间调用一些异步操作。 This discussion of host services concept 对此有明确的表述:
The StartAsync method is asynchronous because we may need to execute some preparation tasks for the job that may fail to execute and compromise the initialization.
希望这能回答您的问题。
如果您正在寻找有关正确实施 IHostedService
的文档,这里有一个很好的文档:Implementing IHostedService in ASP.NET Core 2.0