Очереди задач в C# (.NET): System.Threading.Channels, Hangfire и RabbitMQ

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Очереди задач для C# (.NET): от простого к сложному

Современная разработка на C# (.NET) редко обходится без фоновых задач, отложенной обработки и асинхронных операций. Очереди задач (Job Queues / Message Queues) — ключевой паттерн, позволяющий разгрузить основной поток приложения, гарантировать доставку сообщений и масштабировать обработку. В этой статье мы рассмотрим три популярных подхода к реализации очередей в .NET: встроенный System.Threading.Channels, мощный планировщик Hangfire и промышленный брокер сообщений RabbitMQ с клиентом для .NET.

1. System.Threading.Channels — встроенная очередь в .NET

System.Threading.Channels — это легковесная, потокобезопасная очередь, доступная прямо в .NET (начиная с .NET Core 2.1). Она идеальна для сценариев «производитель-потребитель» внутри одного процесса.

Основные возможности:

  • Асинхронное чтение и запись (await writer.WriteAsync(), await reader.ReadAsync()).
  • Ограниченные и неограниченные каналы (Bounded / Unbounded).
  • Поддержка отмены через CancellationToken.
  • Пакетное чтение (ReadAllAsync).

Пример: простая очередь задач

using System.Threading.Channels;

// Создаем канал с буфером на 100 элементов
var channel = Channel.CreateBounded<string>(100);

// Производитель: добавляем задачи
var producer = Task.Run(async () =>
{
    for (int i = 0; i < 10; i++)
    {
        await channel.Writer.WriteAsync($"Задача {i}");
        await Task.Delay(100);
    }
    channel.Writer.Complete(); // сигнал о завершении
});

// Потребитель: обрабатываем задачи
var consumer = Task.Run(async () =>
{
    await foreach (var item in channel.Reader.ReadAllAsync())
    {
        Console.WriteLine($"Обработано: {item}");
    }
});

await Task.WhenAll(producer, consumer);

Плюсы: нулевая зависимость, высокая производительность, идеально для in-memory очередей в одном приложении.
Минусы: не подходит для распределенных систем — данные теряются при перезапуске.

2. Hangfire — продвинутый планировщик фоновых задач

Hangfire — это популярная библиотека для .NET, которая не только реализует очередь, но и предоставляет веб-дашборд, персистентность (SQL Server, Redis, PostgreSQL), повторные попытки и CRON-расписания.

Ключевые возможности:

  • Fire-and-forget (запуск один раз).
  • Отложенные задачи (Delayed).
  • Повторяющиеся задачи (Recurring) — замена Windows Task Scheduler.
  • Автоматические retry с настраиваемой политикой.
  • Встроенный мониторинг (дашборд).

Пример: базовая настройка Hangfire

// Установка: Install-Package Hangfire
using Hangfire;
using Hangfire.SqlServer;

// Конфигурация в Program.cs (.NET 6+)
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHangfire(config =>
    config.UseSqlServerStorage(builder.Configuration.GetConnectionString("HangfireDb")));
builder.Services.AddHangfireServer();

var app = builder.Build();
app.UseHangfireDashboard(); // /hangfire

// Добавление задач
BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget!"));
BackgroundJob.Schedule(() => Console.WriteLine("Через 5 минут"), TimeSpan.FromMinutes(5));
RecurringJob.AddOrUpdate("my-job", () => Console.WriteLine("Каждую минуту"), Cron.Minutely);

app.Run();

Плюсы: богатая функциональность, сохранение состояния между перезапусками, готовый UI.
Минусы: требует базу данных, не подходит для высоконагруженных распределенных систем (заточен под монолит).

3. RabbitMQ + .NET — распределенная очередь сообщений

RabbitMQ — это промышленный брокер сообщений, реализующий протокол AMQP. Для работы с ним из .NET используется клиентская библиотека RabbitMQ.Client. Это выбор для микросервисной архитектуры, где несколько приложений должны обмениваться задачами.

Базовые понятия:

Рекомендаций