Как реализовать background tasks (фоновые задачи) в ASP.NET Core? Что такое IHostedService?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Реализация фоновых задач в ASP.NET Core
В ASP.NET Core существует несколько подходов для реализации фоновых задач, которые выполняются независимо от HTTP-запросов.
Основные подходы
1. IHostedService и BackgroundService Наиболее рекомендуемый способ для долгосрочных фоновых задач. IHostedService - это базовый интерфейс, который позволяет запускать фоновые задачи вместе с хостом приложения.
public interface IHostedService
{
Task StartAsync(CancellationToken cancellationToken);
Task StopAsync(CancellationToken cancellationToken);
}
Для упрощения реализации используется абстрактный класс BackgroundService:
public abstract class BackgroundService : IHostedService, IDisposable
{
private Task _executingTask;
private readonly CancellationTokenSource _stoppingCts = new();
protected abstract Task ExecuteAsync(CancellationToken stoppingToken);
public virtual Task StartAsync(CancellationToken cancellationToken)
{
_executingTask = ExecuteAsync(_stoppingCts.Token);
return _executingTask.IsCompleted ? _executingTask : Task.CompletedTask;
}
public virtual async Task StopAsync(CancellationToken cancellationToken)
{
if (_executingTask == null) return;
try
{
_stoppingCts.Cancel();
}
finally
{
await Task.WhenAny(_executingTask,
Task.Delay(Timeout.Infinite, cancellationToken));
}
}
}
Пример реализации фоновой задачи:
public class TimedBackgroundService : BackgroundService
{
private readonly ILogger<TimedBackgroundService> _logger;
private readonly PeriodicTimer _timer = new(TimeSpan.FromMinutes(5));
public TimedBackgroundService(ILogger<TimedBackgroundService> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (await _timer.WaitForNextTickAsync(stoppingToken)
&& !stoppingToken.IsCancellationRequested)
{
try
{
_logger.LogInformation("Выполнение фоновой задачи в: {time}",
DateTimeOffset.Now);
// Ваша бизнес-логика
await ProcessDataAsync(stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка в фоновой задаче");
}
}
}
private async Task ProcessDataAsync(CancellationToken cancellationToken)
{
// Реализация обработки данных
await Task.Delay(1000, cancellationToken);
}
}
Регистрация в Program.cs:
builder.Services.AddHostedService<TimedBackgroundService>();
2. Worker Services Отдельный тип проекта для создания длительно работающих служб:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
3. Hangfire и Quartz.NET Библиотеки для продвинутого планирования задач:
// Пример Hangfire
services.AddHangfire(config =>
config.UseSqlServerStorage(connectionString));
services.AddHangfireServer();
// Регистрация рекуррентной задачи
RecurringJob.AddOrUpdate<IMyService>(
"my-recurring-job",
service => service.ProcessData(),
Cron.Daily);
Ключевые аспекты реализации
Обработка ошибок:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
await DoWorkAsync(stoppingToken);
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
_logger.LogError(ex, "Ошибка выполнения задачи");
await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
}
}
}
Инъекция зависимостей:
public class DataProcessingService : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
public DataProcessingService(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken token)
{
using var scope = _scopeFactory.CreateScope();
var repository = scope.ServiceProvider
.GetRequiredService<IDataRepository>();
// Использование скоупированных зависимостей
}
}
Рекомендации по использованию
- Для простых периодических задач используйте
BackgroundService - Для сложного планирования рассмотрите Hangfire или Quartz.NET
- Всегда реализуйте корректную остановку через CancellationToken
- Используйте скоупы для работы с зависимостями с временем жизни Scoped
- Добавляйте логирование для отслеживания выполнения задач
- Конфигурируйте интервалы через appsettings.json
- Тестируйте остановку приложения для избежания утечек ресурсов
Конфигурация через appsettings.json
{
"BackgroundTasks": {
"DataProcessing": {
"IntervalInMinutes": 5,
"Enabled": true,
"BatchSize": 100
}
}
}
IHostedService является фундаментальным строительным блоком для фоновых задач в ASP.NET Core, обеспечивая стандартизированный способ интеграции длительных операций в жизненный цикл приложения с поддержкой dependency injection, конфигурации и корректного завершения работы.