Colas y tareas en segundo plano en C#: cómo acelerar tu aplicación sin dolor

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Por qué tu aplicación C# necesita colas y tareas en segundo plano?

\n\n

Imagina: ejecutas una aplicación web en C#, el usuario hace clic en el botón «Enviar informe», y… el servidor se congela durante 30 segundos mientras se genera el PDF. ¿Te suena familiar? En 2024, los usuarios no perdonan la lentitud. La solución son las colas y las tareas en segundo plano. Transforman el infierno síncrono en un paraíso asíncrono.

\n\n

En este artículo, analizaremos cómo organizar correctamente el procesamiento en segundo plano en C#: desde el Channel<T> integrado hasta el RabbitMQ industrial. Aprenderás cómo sacar el trabajo pesado del hilo principal sin romper la arquitectura. ¡Vamos allá!

\n\n

¿Qué es una cola de tareas y para qué sirve en C#?

\n\n

Una cola (queue) es una estructura de datos FIFO (First In, First Out). En el contexto de C#, es un mecanismo que permite retrasar la ejecución de una tarea para no bloquear el hilo principal. Una tarea en segundo plano es un código que se ejecuta «entre bastidores» mientras el usuario sigue haciendo clic en el sitio web.

\n\n

Escenarios típicos:

\n
    \n
  • Envío de notificaciones por correo electrónico (100 correos = 100 solicitudes SMTP)
  • \n
  • Generación de informes y archivos Excel
  • \n
  • Procesamiento de imágenes cargadas (redimensionamiento, marca de agua)
  • \n
  • Integración con APIs externas (respuestas lentas)
  • \n
  • Registro en base de datos (para no ralentizar la interfaz de usuario)
  • \n
\n\n

Sin colas, la aplicación C# se «congelará» en cada solicitud pesada. Con colas, simplemente colocas la tarea en un búfer y respondes al usuario: «Listo, lo estamos procesando».

\n\n

Opción 1: Tareas en segundo plano con BackgroundService (.NET integrado)

\n\n

La forma más sencilla es usar BackgroundService de Microsoft.Extensions.Hosting. Esta es la clase base para crear servicios en segundo plano en ASP.NET Core. Es ideal para escenarios simples donde no se necesita un enrutamiento de mensajes complejo.

\n\n

Ejemplo: procesador en segundo plano con Channel<T>

\n\n

Escribamos un Productor-Consumidor simple. El Productor (controlador) coloca una tarea en el canal, el Consumidor (BackgroundService) la recoge y la ejecuta.

\n\n
// Paso 1. Creamos un canal (cola segura para hilos)\npublic class TaskChannel\n{\n    private readonly Channel<string> _channel = \n        Channel.CreateBounded<string>(new BoundedChannelOptions(100)\n        {\n            FullMode = BoundedChannelFullMode.Wait\n        });\n\n    public ChannelWriter<string> Writer => _channel.Writer;\n    public ChannelReader<string> Reader => _channel.Reader;\n}\n\n// Paso 2. BackgroundService que lee del canal\npublic class EmailBackgroundService : BackgroundService\n{\n    private readonly TaskChannel _taskChannel;\n\n    public EmailBackgroundService(TaskChannel taskChannel)\n    {\n        _taskChannel = taskChannel;\n    }\n\n    protected override async Task ExecuteAsync(CancellationToken stoppingToken)\n    {\n        await foreach (var emailData in _taskChannel.Reader.ReadAllAsync(stoppingToken))\n        {\n            // Simulación de envío de correo (2 segundos)\n            await Task.Delay(2000, stoppingToken);\n            Console.WriteLine($"Correo enviado: {emailData}");\n        }\n    }\n}\n\n// Paso 3. Controlador que coloca las tareas\n[ApiController]\n[Route("api/email")]\npublic class EmailController : ControllerBase\n{\n    private readonly TaskChannel _taskChannel;\n\n    public EmailController(TaskChannel taskChannel)\n    {\n        _taskChannel = taskChannel;\n    }\n\n    [HttpPost("send")]\n    public IActionResult SendEmail([FromBody] string emailData)\n    {\n        _taskChannel.Writer.TryWrite(emailData);\n        return Accepted(new { message = "Correo puesto en cola" });\n    }\n}\n\n// Paso 4. Registro en Program.cs\nbuilder.Services.AddSingleton<TaskChannel>();\nbuilder.Services.AddHostedService<EmailBackgroundService>();
\n\n

¿Qué sucede aquí? El usuario llama a POST /api/email/send — los datos entran en el ca

Blogs

Book Recommendations