How do you launch a background process in ASPNET Core 3.0?

女生的网名这么多〃 提交于 2020-05-31 01:56:13

问题


I know that the new ASPNET Core 3.0 stack has a number of improvements around hosting processes.

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?


回答1:


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?

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.

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);
        }
    }
}

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.



来源:https://stackoverflow.com/questions/60244633/how-do-you-launch-a-background-process-in-aspnet-core-3-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!