asp.net core 中的计划任务的 IHostedService 和 Task 有什么区别?

Mel*_* NG 6 .net-core asp.net-core

我想每 5 分钟将数据从内存数据库更新到关系数据库。

每个人都建议我使用IHostedServicefrom origin .net core 或其他一些第三方软件包,例如Hangfire.

而我认为它太麻烦了,因为它必须编码很多。

我有一个奇怪的想法,通过循环任务来实现它,例如:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace WebApplication3.Controllers
{
    [Route("api/")]
    public class TestController : Controller
    {
        public TestController()
        {
            Task.Run(() => {
                while (true)
                {
                    Console.WriteLine("123");//code something to transfer data to the database
                    Thread.Sleep(5000);
                    //Task.Delay(5000);
                }
            });
        }
        [Route("ABC")]
        public void ABC()
        { 
    }
}
}
Run Code Online (Sandbox Code Playgroud)

更重要的是,它是如此奇怪,如果我使用它就不会延迟,Task.Delay而如果我使用Thread.Sleep.

我想知道为什么没有人通过Taskof实现它System.Threading.Tasks

也许这是一个愚蠢的问题,但我想找到原因。谢谢你。

Ant*_*dis 1

通常是因为该过程的工作方式。我假设您没有将其放在Task.Run()控制器上而是放在启动上。如果您在控制器上使用它,它只会在每个请求中启动一个新线程。

ASP.NET Core 的工作方式是启动一个进程来侦听传入请求,并为每个请求创建一个新线程。请记住,通过任务运行创建新线程与在后台运行的线程不同。为了让它在后台运行,您需要一个新进程,而不是线程池中的线程。一般来说,这将是一个始终运行并且永远不会被释放来服务其他请求的线程。

更奇怪的是,如果我使用Task.Delay,它不会延迟任何东西,而如果我使用Thread.Sleep,它工作得很好。

使用任务.延迟。它需要 async 关键字并且不会阻塞线程。您可能没有使用该await关键字。

我想知道为什么没有人通过System.Threading.Tasks的Task来实现它?

一般来说,你可以防御性地实施它,但重要的是你对它的控制。每 5 分钟,您的 cpu 和 io 使用量就会激增。但是,如果您将应用程序拆分为同一主机中的 2 个容器,则可以控制每个容器的 CPU 分配量,从而避免 API 性能出现峰值。

编辑:

关于托管服务,您可以从文档中看到 ASP.NET Core 启动一个 Web 服务器,然后在另一个服务上启动 IHostedService。这就是为什么它是首选的。这是一个后台任务,而不是 API 线程池中的线程

编辑:关于 IHostedService 我错了,它不会启动新流程,但您应该使用它,因为它更易于管理,并且它允许您轻松交换新流程并以更加结构化的方式进行维护。