вторник, 26 мая 2026 г.

Qwen, BackgroundServices

Qwen, BackgroundServices

https://chat.qwen.ai/s/350fc6ec-dc1b-4fa5-9d49-351c5f52c222?fev=0.2.57

D:\Projects\VS\2605\BackgroundVersusWorker\Qwen\WebApiWithBackground\WebApiWithBackground.slnx

D:\Projects\VS\2605\BackgroundVersusWorker\Qwen\WebApiWithBackground\WebApiWithBackground01\WebApiWithBackground01.csproj

------------------------------------------------------------------------------------------

Пример 1: BackgroundService внутри Web API
Сценарий: API-сервер, которому нужна периодическая фоновая задача 
(очистка кэша, рассылка уведомлений, синхронизация данных).
Задача работает в том же процессе, делит DI, конфигурацию и БД с основным приложением.
Структура проекта
-------------------------------------------------
WebApiWithBackground/
├── Program.cs
├── Services/
│   └── CacheCleanupService.cs
└── WebApiWithBackground.csproj
--------------------------------------------------
Services/CacheCleanupService.cs
--------------------------------------------------
public class CacheCleanupService : BackgroundService
{
    private readonly ILogger<CacheCleanupService> _logger;
    private readonly IHttpClientFactory _httpClientFactory; // Пример зависимости из DI

    public CacheCleanupService(ILogger<CacheCleanupService> logger, IHttpClientFactory httpClientFactory)
    {
        _logger = logger;
        _httpClientFactory = httpClientFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("🟢 CacheCleanupService запущен");

        // PeriodicTimer корректно обрабатывает отмену и дрейф времени
        using var timer = new PeriodicTimer(TimeSpan.FromSeconds(15));

        try
        {
            while (await timer.WaitForNextTickAsync(stoppingToken))
            {
                await DoCleanupAsync(stoppingToken);
            }
        }
        catch (OperationCanceledException)
        {
            _logger.LogInformation("🟡 CacheCleanupService остановлен (graceful shutdown)");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "🔴 Фатальная ошибка в CacheCleanupService");
            // По умолчанию хост остановится. Если нужно продолжить работу API:
            // throw; // или обернуть в логирование и не бросать дальше
        }
    }

    private async Task DoCleanupAsync(CancellationToken token)
    {
        // Симуляция работы
        await Task.Delay(200, token);
        _logger.LogInformation("✅ Кэш очищен в {Time}", DateTime.UtcNow);
    }
}
-----------------------------------------------------------------------------------
Program.cs
-----------------------------------------------------------------------------------
var builder = WebApplication.CreateBuilder(args);

// Регистрируем фоновый сервис. Он стартует вместе с хостом.
builder.Services.AddHostedService<CacheCleanupService>();

// Стандартные сервисы для Web API
builder.Services.AddHttpClient();

var app = builder.Build();

app.MapGet("/", () => "Web API работает. Фоновая задача запущена в том же процессе.");
app.Run(); // Запускает HTTP-сервер + все IHostedService
------------------------------------------------------------------------------------
Особенности
Работает в том же процессе, что и HTTP-конвейер.
Доступен тот же IServiceProvider, IConfiguration, БД-контексты.
При остановке dotnet run / SIGTERM сначала отключаются новые HTTP-запросы,
затем ждёт завершения stoppingToken, потом процесс выходит.
-------------------------------------------------------------------------------------

Комментариев нет:

Отправить комментарий