Как запустить фоновый процесс в AS PNET Core 3.0? - PullRequest
1 голос
/ 16 февраля 2020

Я знаю, что новый стек AS PNET Core 3.0 имеет ряд улучшений в отношении процессов хостинга.

Мне интересно, как лучше определить и выполнить фоновый процесс из Razor? PageModel? Это означает, что у меня есть какая-то логика c, которая должна запускать что-то в фоновом режиме, а затем на странице Razor не нужно следить за ее результатами, но я бы тоже хотел наблюдать за ней, если это не слишком сложно.

Может кто-нибудь показать мне пример кода или указать мне правильное направление?

1 Ответ

2 голосов
/ 16 февраля 2020

Поскольку это, вероятно, продолжение вашего предыдущего вопроса о IHostedService, я собираюсь предположить, что вы хотите иметь некоторую фоновую службу (как размещенную службу) в вашей ASP . NET Базовое приложение, способное выполнять фоновые задачи. А теперь вы хотите запустить такую ​​задачу с помощью действия контроллера или страницы Razor и выполнить ее в фоновом режиме?

Обычный шаблон для этого - иметь центральное хранилище, которое отслеживает задачи, которые одновременно фоновый сервис и веб-приложение могут получить доступ. Простой способ сделать это - сделать его (поточно-ориентированным) одноэлементным сервисом, к которому могут обращаться обе стороны.

Документы на самом деле показывают простой пример с использованием BackgroundTaskQueue, который является именно этим общим сервисом / состоянием , Если у вас есть работник для определенного вида работы c, вы также можете реализовать его следующим образом:

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

Затем вы можете зарегистрировать реализацию этого в коллекции служб вместе с размещенным фоном. служба, работающая в этой очереди:

services.AddSingleton<JobQueue<MyJob>>();
services.AddHostedService<MyJobBackgroundService>();

Реализация этой размещенной службы может выглядеть следующим образом:

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, чтобы добавить работу в список. Когда фоновая служба готова обработать ее, она будет работать с ней.

Наконец, обратите внимание, что очередь явно находится в памяти, поэтому, если ваше приложение закрывается, список еще не выполненных заданий также ушел. Если вам нужно, вы можете также сохранить эту информацию в базе данных и настроить очередь из базы данных.

...