为什么IHostedService是异步的

5
我知道这是一个设计问题,但我正在尝试理解它以便最好地使用。因此,请将此问题视为澄清如何使用其最大功能的问题。
为什么它没有基于KISS同步设计并具有异步方法(StartAsyncStopAsync)?据我所知,异步在Web请求中的主要优势是释放一些空闲线程以供进一步请求使用,但对于IHostedService来说,这不可能是情况,因为没有请求的概念,并且始终存在一个运行(或暂停)的线程。
1个回答

10

跟着兔子洞一起去吧。

IHostedService的实例由异步方法HostedServiceExecutor.StartAsync()调用(HostedServiceExecutor源代码)。

WebHost.StartAsync()是异步调用HostedServiceExecutor.StartAsync()的(WebHost源代码)。

WebHost实现了IWebHost,其中StartStartAsync均有同步和异步版本。但是,WebHost.Start()的实现只调用了异步版本:

public void Start()
{
    StartAsync().GetAwaiter().GetResult();
}

最后,WebHost.Start()Program.Main 调用(由默认的 ASP.NET Core 项目模板生成):

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

通过这些调用链,我们可以继续回答你的问题:“为什么 IHostedService 是异步的?”并得到“为什么 IWebHost 是异步的?”或者“为什么 C# 7 引入了异步的 Main() 方法?”的答案。

您可以从以下讨论中了解到原因:

那么,主要原因是简化从程序根部调用异步方法。通常程序流程需要调用异步方法(无论是自己实现的还是第三方库的)。 以旧方法为例,我们需要这样做:

public static void Main(string[] args)
{
    SomeAsyncCall().GetAwaiter().GetResult();
}

现在,我们可以使用一种清晰的方式将其全部异步化:

static async Task Main(string[] args)
{
    await SomeAsyncCall();
}
IHostedService.StartAsync()也适用于同样的情况。在主机服务准备期间可能需要调用一些异步操作。关于主机服务概念的这个讨论明确说明了这一点:

StartAsync方法是异步的,因为我们可能需要执行一些准备任务,如果执行失败就会影响初始化。

希望这回答了您的问题。
如果您正在寻找有关适当实现IHostedService的文档,这里是一个很好的选择:在ASP.NET Core 2.0中实现IHostedService

1
很好,谢谢!您的解释也让人明白为什么BackgroundService.StartAsync_executingTask正在运行时返回Task.CompletedTask - 因为否则整个Web应用程序的启动将会被延迟。 - ironstone13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接