La clase Thread
Lear TI Capacitación

Guía de preparación del examen 70-483: Programming in C#

Habilidad: Administración del flujo de un programa
Tema: Implementación del procesamiento asincrónico y de subprocesos
Por Miguel Muñoz Serafín

La clase Thread

Cuando un proceso inicia, el CLR crea automáticamente un hilo (thread) de primer plano para ejecutar el código de la aplicación. Además de este hilo principal de primer plano, un proceso puede crear uno o más hilos para ejecutar una porción del código del programa asociado con el proceso. Estos hilos pueden ejecutarse tanto en primer plano como en segundo plano. La clase System.Threading.Thread nos permite crear y controlar un hilo, establecer su prioridad y obtener su estado. Adicionalmente, también podemos utilizar la clase ThreadPool para ejecutar código en hilos de trabajo que son administrados por el CLR.

Ejercicio
Explorando la clase Thread

Realiza los siguientes pasos para conocer la funcionalidad básica de la clase Thread.

  1. Crea una aplicación de consola utilizando la plantilla Console App (.NET Framework).

    Creamos un hilo especificando en el constructor de la clase Thread un delegado que represente el método que el hilo debe ejecutar. El constructor puede aceptar uno de dos posibles tipos de delegados. El tipo de delegado que le pasemos dependerá del hecho de querer o no pasar un argumento al método a ser ejecutado.

    Si no deseamos pasar un argumento al método a ser ejecutado, utilizamos el delegado ThreadStart y si deseamos pasar un argumento al método a ser ejecutado utilizamos el delegado ParameterizedThreadStart.

  2. Agrega el siguiente código para crear un hilo donde el método a ejecutar no requiere parámetros.

    Thread T = new Thread(() => Console.WriteLine("Hola ThreadStart"));

    El delegado ThreadStart tiene la siguiente firma:

    public delegate void ThreadStart();

    Cualquier método o expresión lambda que no devuelva valor y que no defina parámetros puede ser especificado como delegado del constructor de la clase Thread.

  3. Agrega el siguiente código para crear un hilo donde el método a ejecutar requiere un parámetro.

    Thread T1 = new Thread(
    (obj) => Console.WriteLine($"Hola ParameterizedThreadStart: {obj}"));

    El delegado ParameterizedThreadStart tiene la siguiente firma:

    public delegate void ParameterizedThreadStart(object obj);

    Cualquier método o expresión lambda que no devuelva valor y que defina un parámetro de tipo object puede ser especificado como delegado del constructor de la clase Thread. El método ejecutado por el delegado puede realizar una conversión del valor del parámetro hacia el tipo apropiado.

    Para iniciar la ejecución de un hilo, invocamos al método Start de la instancia Thread.

  4. Agrega el siguiente código para iniciar la ejecución de los hilos creados anteriormente.

    T.Start();
    T1.Start(100);

    Puedes notar que el valor del parámetro del delegado es pasado en la llamada al método Start.

  5. Ejecuta la aplicación y observa el resultado.

    Las instancias de la clase Thread pueden representar hilos de primer plano (foreground thread) o hilos de segundo plano (background thread). Ambos tipos de hilos son idénticos excepto que un hilo de segundo plano no hace que un proceso se mantenga en ejecución si todos los hilos de primer plano han terminado. Una vez que todos los hilos de primer plano han terminado, el motor de tiempo de ejecución detiene todos los hilos de segundo plano y finaliza el proceso.

    De manera predeterminada, al crear y ejecutar un hilo con la clase Thread, el hilo se ejecuta como un hilo de primer plano.

  6. Agrega el siguiente código al final del método Main para ejecutar un proceso en un hilo de primer plano. Puedes notar que utilizamos el método estático Sleep para suspender la ejecución del hilo actual por 2000 milisegundos.

    Thread T2 = new Thread(() =>
    {
    Thread.Sleep(2000);
    Console.WriteLine("El hilo T2 despertó");
    });
    T2.Start();
    Console.WriteLine("Fin del hilo principal");

  7. Ejecuta la aplicación. Puedes notar que la aplicación no finaliza hasta que el hilo T2 finaliza.

    En cualquier momento, podemos modificar un hilo para que se ejecute en segundo plano o primer plano estableciendo el valor de la propiedad IsBackground.

  8. Modifica el siguiente código para mostrar el momento en que empieza la ejecución del hilo y especificar que el hilo T2 se ejecute en segundo plano.

    Thread T2 = new Thread(() =>
    {
    Console.WriteLine("El hilo T2 dormirá");

    Thread.Sleep(2000);
    Console.WriteLine("El hilo T2 despertó");
    });

    T2.IsBackground = true;

    T2.Start();
    Console.WriteLine("Fin del hilo principal");

  9. Ejecuta la aplicación. Puedes notar que la aplicación finaliza sin esperar a que el hilo de segundo plano finalice su ejecución (no se muestra el mensaje “El hilo T2 despertó”).

    La clase Thread expone propiedades que proporcionan información sobre el hilo. En algunos casos también podemos establecer el valor a esas propiedades para controlar la operación del hilo.

  10. Agrega el siguiente código para ejemplificar el uso de las propiedades más comunes de la clase Thread.

    // Obtener el hilo que está ejecutando el código actual
    Thread CT = Thread.CurrentThread;
    // Mostrar el identificador único de un hilo dentro del proceso
    Console.WriteLine($"Id del hilo actual: {CT.ManagedThreadId}");
    // Mostrar el estado de un hilo
    Console.WriteLine($"Estado del hilo actual: {CT.ThreadState}");
    // Mostrar la prioridad de un hilo
    Console.WriteLine($"Prioridad del hilo actual: {CT.Priority}");
    // Mostrar si un hilo es hilo del Thread Pool
    Console.WriteLine(
    $"¿El hilo actual es del Thread Pool? {CT.IsThreadPoolThread}");
    // Mostrar si es un hilo de segundo plano
    Console.WriteLine(
    $"¿El hilo actual es de segundo plano? {CT.IsBackground}");

  11. Ejecuta la aplicación. Podrás ver los valores de las propiedades.

En este ejercicio, exploramos la funcionalidad básica de la clase Thread.

Para más información, se recomienda consultar el siguiente enlace:

Thread Class