Поскольку это, вероятно, продолжение вашего предыдущего вопроса о 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
, чтобы добавить работу в список. Когда фоновая служба готова обработать ее, она будет работать с ней.
Наконец, обратите внимание, что очередь явно находится в памяти, поэтому, если ваше приложение закрывается, список еще не выполненных заданий также ушел. Если вам нужно, вы можете также сохранить эту информацию в базе данных и настроить очередь из базы данных.