Task Queues for C# (.NET): From Simple to Complex
Modern C# (.NET) development rarely goes without background tasks, deferred processing, and asynchronous operations. Task Queues (Job Queues / Message Queues) are a key pattern that allows offloading the main application thread, guaranteeing message delivery, and scaling processing. In this article, we will look at three popular approaches to implementing queues in .NET: the built-in System.Threading.Channels, the powerful scheduler Hangfire, and the industrial message broker RabbitMQ with a .NET client.
1. System.Threading.Channels — Built-in Queue in .NET
System.Threading.Channels is a lightweight, thread-safe queue available directly in .NET (since .NET Core 2.1). It is ideal for producer-consumer scenarios within a single process.
Key Features:
- Async read and write (
await writer.WriteAsync(),await reader.ReadAsync()). - Bounded and unbounded channels.
- Support for cancellation via
CancellationToken. - Batch reading (
ReadAllAsync).
Example: Simple Task Queue
using System.Threading.Channels;
// Create a channel with a buffer of 100 elementsvar channel = Channel.CreateBounded<string>(100);
// Producer: add tasksvar producer = Task.Run(async () =>{ for (int i = 0; i < 10; i++) { await channel.Writer.WriteAsync($"Task {i}"); await Task.Delay(100); } channel.Writer.Complete(); // signal completion});
// Consumer: process tasksvar consumer = Task.Run(async () =>{ await foreach (var item in channel.Reader.ReadAllAsync()) { Console.WriteLine($"Processed: {item}"); }});
await Task.WhenAll(producer, consumer);Pros: zero dependencies, high performance, ideal for in-memory queues in a single application.
Cons: not suitable for distributed systems — data is lost on restart.
2. Hangfire — Advanced Background Job Scheduler
Hangfire is a popular library for .NET that not only implements a queue but also provides a web dashboard, persistence (SQL Server, Redis, PostgreSQL), retries, and CRON schedules.
Key Features:
- Fire-and-forget (run once).
- Delayed jobs.
- Recurring jobs — replacement for Windows Task Scheduler.
- Automatic retries with configurable policy.
- Built-in monitoring (dashboard).
Example: Basic Hangfire Setup
// Installation: Install-Package Hangfireusing Hangfire;using Hangfire.SqlServer;
// Configuration in 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
// Adding jobsBackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget!"));BackgroundJob.Schedule(() => Console.WriteLine("In 5 minutes"), TimeSpan.FromMinutes(5));RecurringJob.AddOrUpdate("my-job", () => Console.WriteLine("Every minute"), Cron.Minutely);
app.Run();Pros: rich functionality, state persistence across restarts, ready-made UI.
Cons: requires a database, not suitable for high-load distributed systems (tailored for monoliths).
3. RabbitMQ + .NET — Distributed Message Queue
RabbitMQ
Also in library
PSR-3 Logger Interface for PHP: Complete Guide with Examples
Working with Dates in JavaScript (Node.js): Popular Libraries
ORM for TypeScript: Comparison of Prisma, TypeORM, and MikroORM
Caching in Java: Redis, Ehcache, Caffeine, Hazelcast — Overview and Examples
ts-pattern for TypeScript: complete guide with examples
Recommendations