问题描述
我想每 5 分钟将数据从内存数据库更新到关系数据库.
I wanna update data from an in-memory database to a relational database every 5 minutes.
每个人都建议我使用来自 origin .net core 的 IHostedService
或其他一些第三方包,例如 Hangfire
.
Everyone suggests me to use the IHostedService
from origin .net core or some other third-party package such as Hangfire
.
然而,我认为它很麻烦,因为它必须编码很多.
Whereas, I think it is so troublesome for it must code much.
我有个奇怪的想法是通过循环任务来实现的,例如:
I have a strange idea that achieves it by the looping task, for example:
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()
{
}
}
}
而且,很奇怪,如果我使用 Task.Delay
它不会延迟,而如果我使用 Thread.Sleep
效果很好.
What's more, it is so strange that it won't delay any if I use the Task.Delay
while it works well if I use the Thread.Sleep
.
我想知道为什么没有人通过System.Threading.Tasks
的Task
实现它?
I wonder why no people achieve it by the Task
of System.Threading.Tasks
?
也许这是一个愚蠢的问题,但我想找到原因.谢谢.
Maybe it is a stupid question but I want to find the reason. Thank you.
推荐答案
通常是因为流程的工作方式.我假设您没有将 Task.Run()
放在控制器上,而是放在启动时.如果您在控制器上使用它,它只会在每个请求中启动一个新线程.
Generally is because of how the process works. I will assume that you don't place the Task.Run()
on the controller but on the startup. If you use it on the controller it will simply start a new thread in each and every request.
ASP.NET Core 的工作方式是启动一个进程来侦听传入的请求,并为每个请求创建一个新线程.请记住,使用任务运行创建新线程与在后台运行的内容不同.为了让它在后台运行,您需要一个新进程而不是线程池中的线程.通常,这将是一个始终运行且永远不会被释放以处理其他请求的线程.
The way ASP.NET Core works is that it starts a process that listens for incoming request and for each request it creates a new thread for it. Remember that creating a new thread with task run is not the same as something running in the background. In order for it to run on the background you would require a new process not a thread from the thread pool. Generally this will be a thread that will always run and never be freed to server other requests.
而且,很奇怪,如果我使用 Task.Delay 就不会延迟,而如果我使用 Thread.Sleep 则效果很好.
使用 Task.Delay.它需要 async 关键字并且不会阻塞线程.您可能没有使用 await
关键字.
Use Task.Delay. It requires the async keyword and it doesnt block the thread. You were probably not using the await
keyword.
我想知道为什么没有人通过 System.Threading.Tasks 的 Task 实现它?
通常您可以坚决地实施它,但重要的是您对它的控制.每 5 分钟您的 cpu 和 io 使用量就会激增.但是,如果您将应用程序拆分为同一主机中的 2 个容器,则您可以控制每个容器的 CPU 分配量,从而避免 API 性能出现峰值.
Generally you could defently implement it but the important thing is the control you have over it. Every 5 minutes your cpu and io usage will spike. But if you split the application in 2 containers in the same host, you can control how much CPU allocation each container will have thus allowing you not to have spikes in performance for the API.
关于托管服务,您可以从文档中看到 ASP.NET Core 启动一个 Web 服务器,然后在不同的服务上启动一个 IHostedService.这就是为什么它是首选.这是一个后台任务,而不是来自 API 线程池的线程
About hosted service as you can see from the documentation ASP.NET Core starts a web server and then starts a IHostedService on a different service. Thats why it's preferred. It's a background task not a thread from the thread pool of your API
关于 IHostedService 我错了,它不会启动新流程,但您应该使用它,因为它更易于管理,并且允许您轻松交换新流程并以更加结构化的方式进行维护.
About the IHostedService I was wrong it doesn't start a new process but you should use it just because it's more manageable and it allows you swap a new process easily and maintain in a much more structured way.
这篇关于asp.net core 中的计划任务的 IHostedService 和 Task 有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!