Multihilo en C#: Mejora el rendimiento y la eficiencia
Un hilo se define como la ruta de ejecución de un programa. Cada hilo define un flujo de control único. Si tu aplicación involucra operaciones complicadas y que consumen mucho tiempo, a menudo es útil establecer diferentes rutas de ejecución o hilos, cada uno realizando un trabajo particular.
Los hilos son procesos ligeros. Un ejemplo común de uso de hilos es la implementación de programación concurrente en sistemas operativos modernos. El uso de hilos ahorra ciclos de CPU desperdiciados y aumenta la eficiencia de una aplicación.
Hasta ahora escribimos programas donde un solo hilo se ejecuta como un único proceso que es la instancia en ejecución de la aplicación. Sin embargo, de esta forma la aplicación solo puede realizar una tarea a la vez. Para hacer que ejecute más de una tarea a la vez, se puede dividir en hilos más pequeños.
Ciclo de vida de un hilo
El ciclo de vida de un hilo comienza cuando se crea un objeto de la clase System.Threading.Thread y termina cuando el hilo termina o completa la ejecución.
Los diversos estados en el ciclo de vida de un hilo son:
Estado No Iniciado - Cuando se crea la instancia del hilo pero no se ha llamado al método Start.
Estado Listo - Cuando el hilo está listo para ejecutarse y espera un ciclo de CPU.
Estado No Ejecutable - Un hilo no es ejecutable cuando:
- Se ha llamado al método Sleep
- Se ha llamado al método Wait
- Bloqueado por operaciones de E/S
Estado Muerto - Cuando el hilo completa la ejecución o es abortado.
El hilo principal
En C#, la clase System.Threading.Thread se usa para trabajar con hilos. Permite crear y acceder a hilos individuales en una aplicación multihilo. El primer hilo en ejecutarse en un proceso se llama el hilo principal.
Cuando un programa C# comienza la ejecución, el hilo principal se crea automáticamente. Los hilos creados usando la clase Thread se llaman hilos hijos del hilo principal. Puedes acceder a un hilo usando la propiedad CurrentThread de la clase Thread.
El siguiente programa demuestra la ejecución del hilo principal:
Demo en vivousing System;
using System.Threading;
namespace AplicacionMultihilo {
class ProgramaHiloPrincipal {
static void Main(string[] args) {
Thread th = Thread.CurrentThread;
th.Name = "HiloPrincipal";
Console.WriteLine("Este es {0}", th.Name);
Console.ReadKey();
}
}
}
Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:
Este es HiloPrincipal
Propiedades y métodos de la clase Thread
La siguiente tabla muestra las propiedades más usadas de la clase Thread:
| Nº | Propiedad y descripción |
|---|---|
| 1 | CurrentContext - Obtiene el contexto actual en el que se ejecuta el hilo. |
| 2 | CurrentCulture - Obtiene o establece la cultura para el hilo actual. |
| 3 | CurrentPrincipal - Obtiene o establece el principal actual del hilo (seguridad basada en roles). |
| 4 | CurrentThread - Obtiene el hilo en ejecución actual. |
| 5 | CurrentUICulture - Obtiene o establece la cultura actual usada por el Resource Manager. |
| 6 | ExecutionContext - Obtiene un objeto ExecutionContext con información sobre los contextos del hilo actual. |
| 7 | IsAlive - Indica el estado de ejecución del hilo actual. |
| 8 | IsBackground - Indica si un hilo es un hilo en segundo plano. |
| 9 | IsThreadPoolThread - Indica si un hilo pertenece al grupo de hilos administrados. |
| 10 | ManagedThreadId - Obtiene un identificador único para el hilo administrado actual. |
| 11 | Name - Obtiene o establece el nombre del hilo. |
| 12 | Priority - Obtiene o establece la prioridad de programación de un hilo. |
| 13 | ThreadState - Obtiene un valor que contiene los estados del hilo actual. |
La siguiente tabla muestra los métodos más usados de la clase Thread:
| Nº | Método y descripción |
|---|---|
| 1 | Abort() - Genera ThreadAbortException para comenzar el proceso de terminación del hilo. |
| 2 | Start() - Inicia un hilo. |
| 3 | Sleep(int millisecondsTimeout) - Hace una pausa en el hilo por un período de tiempo. |
| 4 | Join() - Bloquea el hilo llamador hasta que un hilo termina. |
| 5 | Interrupt() - Interrumpe un hilo en estado WaitSleepJoin. |
| 6 | ResetAbort() - Cancela un Abort solicitado para el hilo actual. |
| 7 | Yield() - Hace que el hilo llamador ceda la ejecución a otro hilo listo para ejecutarse. |
Creación de hilos
Los hilos se crean extendiendo la clase Thread. La clase Thread extendida llama al método Start() para comenzar la ejecución del hilo hijo.
El siguiente programa demuestra el concepto:
Demo en vivousing System;
using System.Threading;
namespace AplicacionMultihilo {
class ProgramaCreacionHilo {
public static void LlamarHiloHijo() {
Console.WriteLine("Hilo hijo inicia");
}
static void Main(string[] args) {
ThreadStart delegadoHijo = new ThreadStart(LlamarHiloHijo);
Console.WriteLine("En Main: Creando el hilo hijo");
Thread hiloHijo = new Thread(delegadoHijo);
hiloHijo.Start();
Console.ReadKey();
}
}
}
Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:
En Main: Creando el hilo hijo Hilo hijo inicia
Gestión de hilos
La clase Thread proporciona varios métodos para gestionar hilos.
El siguiente ejemplo demuestra el uso del método Sleep() para hacer una pausa en un hilo por un período específico:
Demo en vivousing System;
using System.Threading;
namespace AplicacionMultihilo {
class ProgramaCreacionHilo {
public static void LlamarHiloHijo() {
Console.WriteLine("Hilo hijo inicia");
int pausa = 5000;
Console.WriteLine("Hilo hijo en pausa por {0} segundos", pausa / 1000);
Thread.Sleep(pausa);
Console.WriteLine("Hilo hijo reanuda");
}
static void Main(string[] args) {
ThreadStart delegadoHijo = new ThreadStart(LlamarHiloHijo);
Console.WriteLine("En Main: Creando el hilo hijo");
Thread hiloHijo = new Thread(delegadoHijo);
hiloHijo.Start();
Console.ReadKey();
}
}
}
Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:
En Main: Creando el hilo hijo Hilo hijo inicia Hilo hijo en pausa por 5 segundos Hilo hijo reanuda
Destrucción de hilos
El método Abort() se usa para destruir hilos.
El runtime aborta el hilo lanzando una ThreadAbortException. Esta excepción no puede ser capturada, el control se envía al bloque finally, si existe.
El siguiente programa ilustra esto:
Demo en vivousing System;
using System.Threading;
namespace AplicacionMultihilo {
class ProgramaCreacionHilo {
public static void LlamarHiloHijo() {
try {
Console.WriteLine("Hilo hijo inicia");
for (int contador = 0; contador <= 10; contador++) {
Thread.Sleep(500);
Console.WriteLine(contador);
}
Console.WriteLine("Hilo hijo completado");
} catch (ThreadAbortException e) {
Console.WriteLine("Excepción de aborto de hilo");
} finally {
Console.WriteLine("No se pudo capturar la excepción de hilo");
}
}
static void Main(string[] args) {
ThreadStart delegadoHijo = new ThreadStart(LlamarHiloHijo);
Console.WriteLine("En Main: Creando el hilo hijo");
Thread hiloHijo = new Thread(delegadoHijo);
hiloHijo.Start();
Thread.Sleep(2000);
Console.WriteLine("En Main: Abortando el hilo hijo");
hiloHijo.Abort();
Console.ReadKey();
}
}
}
Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:
En Main: Creando el hilo hijo Hilo hijo inicia 0 1 2 En Main: Abortando el hilo hijo Excepción de aborto de hilo No se pudo capturar la excepción de hilo
Lenguaje C
- Elegir el Tratamiento de Rosca Adecuado: Mejorar la Confiabilidad y Reducir el Tiempo de Inactividad
- El Hilo: Tipos, Historia, Producción y Control de Calidad
- Desenredando el hilo digital: El plan de Siemens PLM para manufactura inteligente
- Diámetros menor y mayor de rosca: cómo elegir el tamaño correcto de tornillo
- Comprender los cortahilos: Tipos, usos y aplicaciones
- Iluminación posterior rápida: Captura de más de 1 millón de FPS
- Thread vs. ZigBee: Comparativa Técnica para Ingenieros de IoT
- Edge Computing obtiene un marco claro aprobado por la industria
- Dominar la multihilo en C++: Programación concurrente eficiente
- Programación Multihilo en Python: Técnicas Eficientes de Concurrencia
- Multihilo en Java explicado: Conceptos, ciclo de vida y ejemplos de código prácticos