jueves, 10 de julio de 2014

Receta Multithreading en C# No. 1-6: Establecer la Prioridad de un Thread

Tabla de Contenido

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Enumeración ThreadPriority
3.2 Propiedad Thread.Priority
3.3 Ejemplo de Priorización de Threads
4. Práctica: Código C#
5. Conclusiones
6. Glosario
7. Literatura & Enlaces

0. Introducción

En esta nueva ocasión de preparación de receta multithreading en C# conoceremos el mecanismo de establecimiento del nivel de prioridad para un thread. Conoceremos el uso de la propiedad Priority de la clase Thread (System.Threading) para cambiar el nivel de prioridad de una instancia de esta clase. A través de los ejemplos se demostrará cómo el sistema operativo se encarga de ejecutar cada thread dependiendo de su nivel de prioridad para programar el momento en que el thread debe iniciar su ejecución.

1. Problema

Además de ser necesario conocer el estado de ejecución de un thread (Obtener el Estado de un Thread), es requisito indispensable, ahora, establecer el nivel de prioridad de un thread. Esto para asignar tiempo y recursos de sistema según su nivel (status).

2. Solución

Una de las propiedades de la clase Thread permite establecer el nivel de prioridad en la ejecución de un thread por parte del sistema operativo: Priority. Esta propiedad junto con la enumeración ThreadPriority (System.Threading) solventan el problema planteado en la sección anterior.

3. Discusión de la Solución

La opción de establecimiento del nivel de prioridad permite determinar la cantidad de ciclos de CPU asignados a un thread [1]. Para realizar esta tarea tenemos que hacer uso de los siguientes artefactos de la biblioteca base de clases del Framework .NET:
  • Enumeración ThreadPriority, y 
  • La propiedad Priority de la clase Thread.
A continuación introduciré cada uno de estos artefactos para comprender mejor este mecanismo de priorización (o jerarquía) de la ejecución de threads.

3.1 Enumeración ThreadPriority

La enumeración ThreadPriority [3] se haya declarada en el namespace System.Threading. Inspeccionado la referencia de código (Reference Source) (Introducción a la Referencia Online de Código Fuente de Microsoft .NET Framework) fuente de Microsoft Framework .NET notemos que esta enumeración cuenta con 5 niveles de priorización:


La descripción puntual de cada uno de estos miembros se describen en la Figura 1:
Miembros de la enumeración ThreadPriority
Figura 1. Miembros de la enumeración ThreadPriority.

En tiempo de ejecución se determina el nivel de prioridad de un thread leyendo el valor de la propiedad Priority (que veremos en breve) de cada thread que compite por ciclos de CPU para llevar a cabo su tarea asignada (e.g., método). A lo anterior se puede sumar, que una vez se crea un objeto de la clase Thread, esta tendrá asignada el nivel de prioridad Normal (2).

Por otra parte, en [3] encontramos que:
«The scheduling algorithm used to determine the order o thread execution varies with each operating system. The operating system can also adjust the thread priority dynamically as the user interface's focus is moved between the foreground and the background.»

3.2 Propiedad Thread.Priority

La propiedad Thread.Priority [2] establece y obtiene un valor de la enumeración ThreadPriority, el cual representa el nivel de priorización de ejecución de una instancia de la clase Thread. Esta es su firma:

public ThreadPriority Priority { get; set; }


Estos son los posibles valores asignables a esta propiedad:

  • Highest
  • AboveNormal
  • Normal
  • BelowNormal, y 
  • Lowest

3.2.1 Excepciones


En la Figura 2 [3] se resumen las excepciones que puede generar el asignar un nivel de prioridad (de los mencionados en la sub-sección anterior) (ThreadStateException [7]), o asignación de un valor por por fuera del dominio de la enumeración ThreadPriority (ArgumentException [8]).
Excepciones propiedad Thread.Priority
Figura 2. Excepciones propiedad Thread.Priority.

3.3 Ejemplo de priorización de Threads

En este ejemplo se demuestra el establecimiento de prioridad de dos threads con la enumearción ThreadPriority.

Archivo C# UsoEnumThreadPriority.cs [enlace alternativo]:

En las líneas 6-61 se declara la clase Priorizacion. Esta clase posee los siguientes miembros:
  • contador (línea 8): para contar las veces que se ejecuta el ciclo do while de la líneas 48-55.
  • Thread (línea 9): instancia de Thread asociado a la clase.
  • Construtor 0-parámeros (líneas 35-40): inicializa los atributos anteriores.
  • Tarea (líneas 42-60): este método se encarga de incrementar el contador asociado a una instancia de Priorizacion. Además muestras de inicio y fin de la ejecución junto con el nombre asignado desde código cliente.
En la clase de prueba UsoThreadPriority (líneas 63-88) se realizan las siguientes acciones:
  • Líneas 68-69: Creación de dos instancias de la clase Priorizacion.
  • Líneas 42-73: A los threads asociados a las instancias de Priorizacion se les asignan las siguientes prioridades:

    ThreadPriority.AboveNormal ThreadPriority.Lowest

    Los dos threads se inician (líneas 76 y 77) y se espera a que finalicen (líneas 80 y 81).
  • Líneas 85 y 86: Muestra los resultados de la ejecución de los threads de las instancias Priorizacion.
Compilación:

  1. csc /target:exe UsoEnumThreadPriority.cs

Ejecución assembly:

  1. .\UsoEnumThreadPriority.cs


> Prueba de ejecución (local):
Ejecución assembly UsoEnumThreadPriority.exe
Figura 3. Ejecución assembly UsoEnumThreadPriority.exe.

4. Práctica: Código C#

En este nuevo ejemplo vamos a reunir varios de los conceptos de la sección anterior, y usaremos algunas primitivas del sistema operativo para asociar la ejecución de un thread en un determinado hilo de procesador.


Compilación:


  1. csc /target:exe EjecucionThreadEnCore.cs

Ejecución assembly:


  1. .\EjecucionThreadEnCore.exe

> Prueba de ejecución (ideone).

Resultado ([Nota: Puede variar por cada ejecución.]):
Prioridad del thread Main: Lowest
Ejecución sobre todos los núcleos (cores) disponibles...

El thread `Thread no. 2` con prioridad      Lowest tiene un contador de   321,775,972.

El thread `Thread no. 1` con prioridad      Lowest tiene un contador de   320,151,802.

Ejecución sobre un único núcleo (core)...

El thread `Thread no. 2` con prioridad      Lowest tiene un contador de   361,832,494.

El thread `Thread no. 1` con prioridad      Lowest tiene un contador de   362,133,794.

5. Conclusiones

El uso de la enumeración ThreadPriority permite establecer el nivel de prioridad para le ejecución de un thread. Los valores de esta enumeración se pueden asignar a la propiedad Priority de cualquier instancia de Thread. Interntamente, la ejecución de cada thread se realiza dependiendo de su nivel de prioridad: un thread con alta prioridad (e.g., Highest) obtendrá tiempo (ciclos) de procesador que cualquier otro thread con una prioridad inferior (e.g., AboveNormal, o Normal). La próxima receta multithreading la dedicaremos a explorar los conceptos de threads de primer y segundo plano.

Glosario

  • CLR
  • CPU
  • Hilo
  • Prioridad
  • Priorización
  • Procesador
  • Thread

Literatura & Enlaces

[1]: Multithreading in C# 5.0 Cookbook by Eugene Agafonov. Copyright 2013 Eugene Agafonov, 978-1-84969-764-4.
[2]: Thread.Priority Property (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.thread.priority(v=vs.110).aspx
[3]: ThreadPriority Enumeration (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.threadpriority(v=vs.110).aspx
[4]: Receta Multithreading en C# No. 1-5: Obtener el Estado de un Thread | OrtizOL - Experiencias Construcción Software (xCSw) - http://ortizol.blogspot.com/2014/07/receta-csharp-no-4-6-ejecucion-de-un-metodo-sobre-un-nuevo-thread.html
[5]: OrtizOL - Experiencias Construcción Software (xCSw): Introducción a la Referencia Online de Código Fuente de Microsoft .NET Framework - http://ortizol.blogspot.com/2014/05/introduccion-la-referencia-online-de.html
[6]: Reference Source - http://referencesource.microsoft.com/#mscorlib/system/threading/threadpriority.cs
[7]: ThreadStateException Class (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.threadstateexception(v=vs.110).aspx
[8]: ArgumentException Class (System) - http://msdn.microsoft.com/en-us/library/system.argumentexception(v=vs.110).aspx


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.