Concurrencia y subprocesamiento múltiple en C#: de la A a la Z — guía completa

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

Introducción: ¿por qué se necesita concurrencia en C#?

Las aplicaciones modernas requieren cada vez más la ejecución de varias operaciones simultáneamente. El usuario espera que la interfaz no se "congele" al cargar datos, y que el servidor pueda procesar miles de solicitudes en paralelo. En C# (.NET), para resolver estos problemas se utiliza la concurrencia — la capacidad de un programa para ejecutar varias tareas en intervalos de tiempo superpuestos — y el subprocesamiento múltiple — la implementación de la concurrencia mediante múltiples hilos de ejecución.

En este artículo, analizaremos los conceptos clave: desde los Thread básicos hasta los modernos async/await y Parallel. Aprenderá a elegir la herramienta adecuada para cada tarea y a evitar errores típicos como los bloqueos mutuos (deadlocks) y las condiciones de carrera (race conditions).



1. Fundamentos: Thread y ThreadPool

Trabajo con hilos mediante Thread

La clase System.Threading.Thread es la forma de más bajo nivel para crear hilos. Cada hilo tiene su propia pila y se ejecuta de forma independiente. Ejemplo de creación e inicio de un hilo:

using System;using System.Threading;

class Program{ static void Main() { Thread thread = new Thread(DoWork); thread.Start(); // El hilo principal continúa su trabajo for (int i = 0; i < 5; i++) { Console.WriteLine($"Hilo principal: {i}"); Thread.Sleep(100); } thread.Join(); // Esperamos a que finalice el hilo secundario }

static void DoWork() { for (int i = 0; i < 5; i++) { Console.WriteLine($"Hilo de trabajo: {i}"); Thread.Sleep(150); } }}

Importante: Crear un nuevo hilo es una operación costosa. Para la creación frecuente de hilos de corta duración, es mejor usar ThreadPool.



ThreadPool — grupo de hilos

ThreadPool gestiona un conjunto de hilos de trabajo que se reutilizan. Esto es más eficiente que crear un Thread manualmente. Ejemplo:

ThreadPool.QueueUserWorkItem(state =>{    Console.WriteLine("La tarea se ejecuta en el grupo de hilos");    Thread.Sleep(500);    Console.WriteLine("Tarea completada");});

Console.WriteLine("El hilo principal continúa su trabajo");Console.ReadKey();

Limitación: No puede controlar directamente la prioridad o el nombre del hilo del grupo. Para un control más preciso, use Task.



2. Task y Task Parallel Library (TPL)

Task — el enfoque moderno

A partir de .NET 4.0, Task se convirtió en la herramienta principal para operaciones asíncronas. Abstrae los hilos y permite trabajar con los resultados de la ejecución. Ejemplo:

using System;using System.Threading.Tasks;

class Program{ static async Task Main() { Task<int> task = Task.Run(() => ComputeResult(10)); // Se puede hacer otro trabajo Console.WriteLine("Esperando el resultado..."); int result = await task; Console.WriteLine($"Resultado: {result}"); }

static int ComputeResult(int value) { Task.Delay(1000).Wait(); // Simulación de una operación larga return value * 2; }}

Ventajas clave:

  • Devuelve un resultado mediante Task<T>
  • Admite cancelación mediante CancellationToken
  • Permite combinar tareas (ContinueWith, WhenAll, WhenAny)
  • Integrado con async/await


Parallel — para bucles paralelos

La clase Parallel simplifica la ejecución de bucles con paralelización. Ejemplo:

using System;using System.Threading.Tasks;

class Program{ static void Main()\

Blogs

Book Recommendations