Concurrencia y subprocesamiento múltiple en C#: Guía completa para desarrolladores .NET

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

Concurrencia y subprocesamiento múltiple en C#: desde Thread hasta async/await



Las aplicaciones modernas requieren cada vez más la ejecución simultánea de varias tareas: desde el procesamiento de solicitudes de un servidor web hasta cálculos paralelos en programas de escritorio. En C# (.NET) existe un potente arsenal de herramientas para esto, desde hilos clásicos (Thread) hasta construcciones de alto nivel como async/await y la biblioteca Task Parallel Library (TPL). En este artículo, analizaremos los conceptos clave de concurrencia y subprocesamiento múltiple, su aplicación práctica y las mejores prácticas.



¿Qué es concurrencia y subprocesamiento múltiple?



Antes de pasar al código, es importante entender la diferencia entre estos conceptos:



  • Concurrencia (Concurrency) — la capacidad de un programa para ejecutar varias tareas, alternando entre ellas, creando la ilusión de ejecución simultánea. Esto se puede implementar incluso en un núcleo de procesador.
  • Subprocesamiento múltiple (Multithreading) — una forma de concurrencia en la que varios hilos (threads) se ejecutan físicamente al mismo tiempo en un procesador multinúcleo.
  • Paralelismo (Parallelism) — un subconjunto del subprocesamiento múltiple, donde diferentes partes de una tarea se ejecutan estrictamente al mismo tiempo en diferentes núcleos.


En C#, puede usar tanto hilos de bajo nivel como abstracciones que gestionan los hilos automáticamente. La elección depende de la tarea: para operaciones I/O-bound (trabajo con archivos, red) es mejor usar async/await, y para CPU-bound (cálculos) — Parallel.For o Task.



Creación y gestión de hilos: clase Thread



La clase System.Threading.Thread es la forma más baja de trabajar con hilos en C#. Proporciona control total, pero requiere una sincronización cuidadosa.



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 termine el hilo secundario Console.WriteLine("Trabajo completado."); }

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


Problemas de la gestión manual de hilos:

  • Complejidad de sincronización (condiciones de carrera, deadlocks).
  • Alto costo general de creación y destrucción de hilos.
  • Falta de soporte integrado para devolver un resultado.


Por lo tanto, en el C# moderno se prefiere usar Task Parallel Library.



Task Parallel Library (TPL) y async/await



La clase Task del espacio de nombres System.Threading.Tasks representa una operación asíncrona. En combinación con las palabras clave async y await, permite escribir código asíncrono que parece síncrono.



Ejemplo básico con Task



using System;using System.Threading.Tasks;

class Program{ static async Task Main() { Console.WriteLine("Inicio del trabajo.");

// Iniciamos una tarea asíncrona Task<int> task = CalculateAsync(10);

// Mientras la tarea se ejecuta, podemos hacer otra cosa Console.WriteLine("Haciendo otro trabajo...");

// Esperamos el resultado int result = await task; Console.WriteLine($"Resultado: {result}"); }

static async Task<int> CalculateAsync(int number) { await Task.Delay(1000); // Simulación de una operación larga return number * number; }}

Blogs

Book Recommendations