Приходилось ли создавать сервисы (фоновые службы)?

Ответ

Да, создавал различные типы сервисов для выполнения фоновых задач и длительных операций.

1. Фоновые сервисы в ASP.NET Core (BackgroundService): Идеально для задач внутри веб-приложения: отправка email, обработка очередей, кэширование.

public class TimedHostedService : BackgroundService
{
    private readonly ILogger<TimedHostedService> _logger;
    private readonly IServiceScopeFactory _scopeFactory;

    public TimedHostedService(ILogger<TimedHostedService> logger, IServiceScopeFactory scopeFactory)
    {
        _logger = logger;
        _scopeFactory = scopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service running.");
        using PeriodicTimer timer = new(TimeSpan.FromSeconds(5));

        try
        {
            while (await timer.WaitForNextTickAsync(stoppingToken))
            {
                await using (var scope = _scopeFactory.CreateAsyncScope())
                {
                    var scopedProcessor = scope.ServiceProvider
                        .GetRequiredService<IScopedProcessingService>();
                    await scopedProcessor.DoWorkAsync(stoppingToken);
                }
            }
        }
        catch (OperationCanceledException)
        {
            _logger.LogInformation("Timed Hosted Service is stopping.");
        }
    }
}
// Регистрация в Program.cs: builder.Services.AddHostedService<TimedHostedService>();

2. Windows Services (ранее NT Services): Для автономных служб, работающих под управлением Windows Service Control Manager (SCM).

using System.ServiceProcess;

public class MyWindowsService : ServiceBase
{
    private BackgroundWorker _worker;

    protected override void OnStart(string[] args)
    {
        _worker = new BackgroundWorker();
        _worker.DoWork += (s, e) => { /* Долгая фоновая работа */ };
        _worker.RunWorkerAsync();
    }

    protected override void OnStop()
    {
        _worker?.CancelAsync();
        // Освобождение ресурсов
    }
}
// Установка через sc.exe create "MyService" binPath="путь_к_exe"

3. Современные альтернативы:

  • Hangfire / Quartz.NET: Для сложного планирования фоновых заданий.
  • Azure Functions / AWS Lambda: Для бессерверного выполнения задач.
  • Worker Services в .NET: Шаблон для создания длительно работающих служб с поддержкой контейнеризации (Docker).

Ключевые аспекты: устойчивость к ошибкам, корректное логирование, поддержка graceful shutdown и конфигурируемость.

Ответ 18+ 🔞

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

1. Фоновые службы в ASP.NET Core (BackgroundService): Это когда тебе надо, чтобы внутри самого веб-приложения что-то тикало, как часы. Удобно, не надо отдельный сервис городить.

public class TimedHostedService : BackgroundService
{
    private readonly ILogger<TimedHostedService> _logger;
    private readonly IServiceScopeFactory _scopeFactory;

    public TimedHostedService(ILogger<TimedHostedService> logger, IServiceScopeFactory scopeFactory)
    {
        _logger = logger;
        _scopeFactory = scopeFactory;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service running.");
        using PeriodicTimer timer = new(TimeSpan.FromSeconds(5));

        try
        {
            while (await timer.WaitForNextTickAsync(stoppingToken))
            {
                await using (var scope = _scopeFactory.CreateAsyncScope())
                {
                    var scopedProcessor = scope.ServiceProvider
                        .GetRequiredService<IScopedProcessingService>();
                    await scopedProcessor.DoWorkAsync(stoppingToken);
                }
            }
        }
        catch (OperationCanceledException)
        {
            _logger.LogInformation("Timed Hosted Service is stopping.");
        }
    }
}
// Регистрация в Program.cs: builder.Services.AddHostedService<TimedHostedService>();

Вот смотри, суть в чём: создаёшь таймер, и он каждые пять секунд, как долбоёб назойливый, дёргает твою логику. А IServiceScopeFactory — это чтобы зависимости правильно резолвить, а то без него влетит в дедлок, как курьер в лифт с зеркалами.

2. Windows Services (старые добрые NT Services): Это уже для монстров, которые должны висеть в системе всегда, даже когда пользователь не залогинен. Типа демонов на Windows.

using System.ServiceProcess;

public class MyWindowsService : ServiceBase
{
    private BackgroundWorker _worker;

    protected override void OnStart(string[] args)
    {
        _worker = new BackgroundWorker();
        _worker.DoWork += (s, e) => { /* Долгая фоновая работа */ };
        _worker.RunWorkerAsync();
    }

    protected override void OnStop()
    {
        _worker?.CancelAsync();
        // Освобождение ресурсов
    }
}
// Установка через sc.exe create "MyService" binPath="путь_к_exe"

Честно? Старая школа. Запустил — и забыл. Пока кто-то вручную не остановит или система не грохнется. Установка через консоль — отдельный квест на потерю нервных клеток, ёпта.

3. Ну и куда же без модных альтернатив:

  • Hangfire / Quartz.NET: Это когда тебе нужно не просто "раз в пять секунд", а сложное расписание, вроде "в последнюю пятницу месяца в 3:15 ночи, но только если нет затмения". Мощные штуки, но и возни с ними — овердохуища.
  • Azure Functions / AWS Lambda: Бессерверное — звучит круто, пока не начнёшь считать деньги за каждый вызов. Но для спорадических задач — вообще огонь, не надо париться об инфраструктуре.
  • Worker Services в .NET: Свежая фишка, специально для создания долгоживущих служб, которые можно в Docker запихнуть и забыть, как страшный сон.

Главное во всём этом, чувак — не накосячить с обработкой ошибок и остановкой. Чтобы служба не сдохла молча, как муха в янтаре, а хотя бы в лог написала, от чего кончилась. И чтобы её можно было аккуратно остановить, а не убивать через Task Manager, как последнего пидораса. Всё остальное — уже детали.