【问题标题】:Why IHostedService is async为什么 IHostedService 是异步的
【发布时间】:2018-03-15 22:46:16
【问题描述】:

我知道这是一个设计问题,但我正在努力理解这一点,以便以最佳方式使用它。因此,请将此问题视为对如何使用其最大功能的说明。

为什么不设计基于 KISS 的同步并有异步方法(StartAsync,StopAsync),AFAIK,在 web 请求中异步的主要好处是让一些空闲线程被释放以用于进一步服务请求,但IHostedService 并非如此,因为没有请求的概念,并且总是有一个正在运行(或挂起)的线程。

【问题讨论】:

    标签: .net asynchronous asp.net-core .net-core .net-core-2.0


    【解决方案1】:

    我们去兔子洞吧。

    IHostedService 的实例由异步的 HostedServiceExecutor.StartAsync() 调用 (HostedServiceExecutor source code)。

    HostedServiceExecutor.StartAsync() 由异步调用的WebHost.StartAsync() (WebHost source code) 调用。

    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 引入了 async Main() 方法?”。

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

    嗯,主要原因是为了简化从程序根目录对异步方法的调用。通常程序流程需要调用异步方法(您自己的实现或第三方库)。 使用旧方法,我们将执行以下操作:

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

    但现在我们可以以一种干净的方式让它一直异步:

    static async Task Main(string[] args)
    {
        await SomeAsyncCall();
    }
    

    这同样适用于IHostedService.StartAsync()。它可能需要在主机服务准备期间调用一些异步操作。 This discussion 的主机服务概念对此有明确的说明:

    StartAsync 方法是异步的,因为我们可能需要执行 可能无法执行的作业的一些准备任务和 破坏初始化。

    希望这能回答你的问题。

    如果您正在寻找有关正确实施 IHostedService 的文档,这里有一个很好的文档:Implementing IHostedService in ASP.NET Core 2.0

    【讨论】:

    • 不错,谢谢!您的解释也很明显,如果 _executingTask 正在运行,为什么 BackgroundService.StartAsync 返回 Task.CompletedTask - 因为否则整个网络应用程序的启动将被延迟
    猜你喜欢
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 1970-01-01
    • 2019-10-11
    • 2020-04-20
    • 1970-01-01
    相关资源
    最近更新 更多