csharp-threads

Qué son y cómo usar Threads en C#

En C#, los threads (hilos) son una forma de conseguir la programación concurrente y paralela. Nos permiten dividir la ejecución de un programa en múltiples tareas que pueden correr simultáneamente.

En muchos casos necesitamos realizar tareas simultáneamente, como acceder a una base de datos mientras se muestra una animación en la interfaz de usuario. Aquí es donde los threads permiten dividir el trabajo en tareas concurrentes.

Un thread es la unidad más pequeña de procesamiento en un programa. Normalmente, un programa tiene al menos un hilo, llamado hilo principal (main thread), que es el responsable de ejecutar las instrucciones en un orden secuencial.

Crear y Ejecutar un Thread

En C#, se puede crear un hilo instanciando la clase Thread y asignándole un método para ejecutar. A continuación, llamamos al hilo llamando al método .Start().

using System;
using System.Threading;

public class Program
{
    public static void Main()
    {
        // Crear un nuevo hilo
        Thread nuevoHilo = new Thread(TareaEnSegundoPlano);
        nuevoHilo.Start(); // Iniciar el hilo

        // Tarea en el hilo principal
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine("Hilo principal en ejecución...");
            Thread.Sleep(1000);
        }
    }

    public static void TareaEnSegundoPlano()
    {
        for (int i = 0; i < 5; i++)
        {
            Console.WriteLine("Hilo secundario en ejecución...");
            Thread.Sleep(1000);
        }
    }
}

El método que se ejecutará en el nuevo hilo debe ser de tipo void y no debe tener parámetros (o se deben manejar los parámetros de manera alternativa).

Métodos y propiedades útiles de Thread

La clase Thread proporciona varios métodos y propiedades útiles:

  • Thread.Sleep(int milliseconds): Suspende la ejecución del hilo actual durante el número de milisegundos especificado. Útil para realizar pausas.
  • Thread.Join(): Hace que el hilo principal espere a que el hilo secundario complete su tarea antes de continuar. Esto es útil para asegurar que un hilo ha finalizado antes de continuar con la ejecución.
  • IsAlive: Propiedad que indica si el hilo está en ejecución.
  • Priority: Permite establecer la prioridad del hilo (Baja, Normal, Alta), lo que afecta al orden de ejecución relativa.
Thread nuevoHilo = new Thread(TareaEnSegundoPlano);
nuevoHilo.Start();

// Espera a que el nuevo hilo termine antes de continuar
nuevoHilo.Join();

Console.WriteLine("Hilo secundario finalizado. Continuando en el hilo principal.");

Sincronización de hilos

La sincronización de hilos es fundamental para evitar problemas como condiciones de carrera (race conditions) o bloqueos (deadlocks).

El uso de la palabra clave lock en C# permite que solo un hilo acceda a un recurso compartido en un momento dado, evitando así conflictos.

using System;
using System.Threading;

public class CuentaBancaria
{
    private decimal saldo = 0;
    private object bloqueo = new object();

    public void Depositar(decimal cantidad)
    {
        lock (bloqueo)
        {
            saldo += cantidad;
            Console.WriteLine($"Depósito de {cantidad}. Saldo actual: {saldo}");
        }
    }
}

public class Program
{
    public static void Main()
    {
        CuentaBancaria cuenta = new CuentaBancaria();

        // Crear varios hilos para simular depósitos simultáneos
        Thread hilo1 = new Thread(() => cuenta.Depositar(100));
        Thread hilo2 = new Thread(() => cuenta.Depositar(200));

        hilo1.Start();
        hilo2.Start();

        hilo1.Join();
        hilo2.Join();
    }
}

En este ejemplo, la palabra clave lock garantiza que solo un hilo pueda acceder a la operación de depósito al mismo tiempo.