如何在ASPNET Core 3.0中启动后台进程? [英] How do you launch a background process in ASPNET Core 3.0?
问题描述
我知道新的ASPNET Core 3.0堆栈在托管过程方面有许多改进.
I know that the new ASPNET Core 3.0 stack has a number of improvements around hosting processes.
我对能够从Razor PageModel定义和执行后台进程的最佳方法感到好奇吗?意味着我有一些逻辑,需要在后台启动某些东西,然后Razor页面不需要监视它的结果,但是如果这不太难的话,我也希望能够观察到它.
I am curious about the best way to be able to define and execute a background process from a Razor PageModel? Meaning I have some logic that needs to start something in the background and then that Razor page doesn't need to monitor it's outcome, but I would like to be able to observe it too if that's not too hard.
有人可以给我看一个代码示例或向我指出正确的方向吗?
Can someone show me a code sample or point me in the right direction?
推荐答案
由于这可能是您上一个关于 IHostedService
,我假设您要在能够执行后台任务的ASP.NET Core应用程序中拥有一些后台服务(作为托管服务).现在您想通过控制器或Razor页面操作触发此类任务,并使其在后台执行?
Since this is probably a follow-up from your previous question about IHostedService
, I am going to assume that you want to have some background service (as a hosted service) within your ASP.NET Core application that is able to perform background tasks. And now you want to trigger such a task through a controller or Razor page action and have it executed in the background?
一个常见的模式是拥有一些中央存储,以跟踪后台服务和Web应用程序都可以访问的任务.一种简单的方法是使它成为双方都可以访问的(线程安全的)单例服务.
A common pattern for this is to have some central storage that keeps track of the tasks which both the background service and the web application can access. A simple way to do this is to make it a (thread-safe) singleton service that both sides can access.
该文档实际上显示了一个使用 BackgroundTaskQueue
的简单示例,该示例正是该共享服务/状态.但是,如果您有从事某种特定工作的工人,也可以这样实现:
The docs actually show a simple example using a BackgroundTaskQueue
which is exactly that shared service/state. If you have a worker for a specific kind of job though, you could also implement it like this:
public class JobQueue<T>
{
private readonly ConcurrentQueue<T> _jobs = new ConcurrentQueue<T>();
private readonly SemaphoreSlim _signal = new SemaphoreSlim(0);
public void Enqueue(T job)
{
_jobs.Enqueue(job);
_signal.Release();
}
public async Task<T> DequeueAsync(CancellationToken cancellationToken = default)
{
await _signal.WaitAsync(cancellationToken);
_jobs.TryDequeue(out var job);
return job;
}
}
然后您可以在服务集合中注册该实现的实现,以及在此队列上工作的托管后台服务:
You can then register an implementation of this with the service collection along with a hosted background service that works on this queue:
services.AddSingleton<JobQueue<MyJob>>();
services.AddHostedService<MyJobBackgroundService>();
该托管服务的实现如下所示:
The implementation of that hosted service could then look like this:
public class MyJobBackgroundService : BackgroundService
{
private readonly ILogger<MyJobBackgroundService> _logger;
private readonly JobQueue<MyJob> _queue;
public MyJobBackgroundService(ILogger<MyJobBackgroundService> logger, JobQueue<MyJob> queue)
{
_logger = logger;
_queue = queue;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var job = await _queue.DequeueAsync(stoppingToken);
// do stuff
_logger.LogInformation("Working on job {JobId}", job.Id);
await Task.Delay(2000);
}
}
}
在控制器操作或Razor页面模型中,您只需要注入 JobQueue< MyJob>
,然后调用 Enqueue
将作业添加到列表.一旦后台服务准备好处理它,它将在其上工作.
In a controller action or a Razor page model, you then just need to inject the JobQueue<MyJob>
and then call Enqueue
on it to add a job to the list. Once the background service is ready to process it, it will then work on it.
最后请注意,队列显然在内存中,因此,如果您的应用程序关闭,则尚未执行的作业列表也将消失.如果需要,您当然也可以将这些信息保留在数据库中,并从数据库中设置队列.
Finally note that the queue is obviously in-memory, so if your application shuts down, the list of yet-to-do jobs is also gone. If you need, you could also persist this information within a database of course and set up the queue from the database.
这篇关于如何在ASPNET Core 3.0中启动后台进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!