jueves, 17 de julio de 2014

Receta Multithreading en C# No. 1-7: Threads Foreground y Background

Índice

0. Introducción
1. Problema
2. Solución
3. Discusión de la Solución
3.1 Propiedad Thread.IsBackground
3.1.1 Ejemplos de uso
3.1.1.1 Foreground Vs background
3.1.1.2 Aplicación WinForms
4. Práctica C#
5. Artefactos
6. Conclusiones
7. Glosario
8. Literatura & Enlaces

0. Introducción

Ahora dedicaremos tiempo y recursos para estudiar los threads de primer plano (o foreground) y threads de segundo plano (o background). Esta receta destacará la diferencia entre estos dos tipos de threads y su propósito en una aplicación multithreading. Crearemos un ejemplo con una aplicación WinForms en donde instanciaremos dos threads, uno foreground y otro background, y observaremos lo que ocurre con estos dos threads después de cerrar la aplicación. ¡Empecemos!

1. Problema

Ya contamos con los esenciales para la creación y manipulación de threads en ejecución (ver recetas anteriores); ahora queremos ir más a fondo y conocer las categorías de ejecución de un thread. El propósito es diferenciar estas categorías para asignar procesos de acuerdo a su jerarquía de ejecución en un dominio de aplicación o proceso.

2. Solución

En el Framework .NET encontramos dos categorías de threads:
  • Foreground (primer plano), y 
  • Background (segundo plano)
La clase Thread cuenta con la propiedad IsBackground para establecer o recuperar la categoría o plano de ejecución del thread. (Estudiáremos esta propiedad en la siguiente sección.)

3. Discusión de la Solución

Los threads creados bajo la CLR se categorizan en dos únicas categorías de plano de ejecución:
  • Foreground (o thread de primer plano), y
  • Background (o thread de segundo plano)
Referente al término plano, es el ámbito de ejecución de un thread. Un thread foreground se mantiene en ejecución a pesar de que el thread principal (por decir, Main) desde donde ha sido creado, ya haya finalizado su ciclo de ejecución. Lo anterior no ocurre con un thread background, una vez que el thread de donde fue instanciado haya finalizado o la aplicación haya sido cerrada, este también finalizará (no le da tiempo a que finalice las tareas asociadas) [2].

Leamos esta nota encontrada [2]:
Finalización de threads background en dominios de aplicación
Figura 1. Finalización de threads background en dominios de aplicación.
Versión texto:
«When the runtime stops a background thread because the process is shutting down, no exception is thrown in the thread. However, when threads are stopped because the AppDomain.Unload method unloads the application domain, a ThreadAbortException is thrown in both foreground and background threads.»
Esto nos da entender que la finalización de threads por parte de la CLR, en un proceso no generá ningún tipo de excepción. Mientras que descargar (cfr. Descarga de Assemblies y Dominios de Aplicación) un dominio de aplicación con el método AppDomain.Unload, se genera la excepción ThreadAbortException (cfr. Abortar un Thread en Ejecución).


Continuando, la clase Thread (namespace System.Threading) cuenta con la propiedad IsBackground que permite establecer y obtener el plano de ejecución de un thread. Conozcamos más acerca de esta propiedad en la siguiente sección.

3.1 Propiedad Thread.IsBackground

La propiedad IsBackground posee la siguiente firma [8]:

public bool IsBackground { get; set; }

Descripción puntual:
  • Valor de propiedad:
    • true: si el thread se ha de ejecutar en segundo plano (background).
    • false: si el thread se ha de ejecutar en primer plano (foreground).
Cuando creamos un thread a partir de la clase Thread el valor por defecto de esta propiedad es false.

Veamos un par de ejemplos de uso de esta propiedad.

3.1.1 Ejemplos de uso

3.1.1.1 Foreground vs background threads

En este primer ejemplo resaltaremos las diferencias entre los threads foreground y background.

Los métodos:
  • Imprimir1 (líneas 62-73): imprime en pantalla la actividad de un thread en ejecución.
  • Imprimir2 (líneas 77-88): ídem.
  • Retraso (líneas 91-98): simula retraso de ejecución de threads foreground y background.
  • EjecutarThreadForeground (líneas 101-105): crea un thread que se ha de ejecutar en primer plano (foreground).
  • EjecutarThreadBackground (líneas 108-114): crea un thread que se ha de ejecutar en segundo plano (background):

    background.IsBackground = true;
En el método Main (líneas 8-58) ocurren las siguientes acciones:
  • Líneas 14 y 15: Creación de dos threads. En las líneas 18 y 19 se les asigna un identificador textual para reconocer la actividad de ejecución en los métodos Imprimir1 y Imprimir2.
El resto del código (líneas 29-55) construye un menú basado en texto para las siguientes opciones:
  1. Ejecución en paralelo.
  2. Demostración ejecución threads foreground y background.
Compilación:

  1. csc /target:exe ForegroundVsBackground.cs

Ejecución assembly:

  1. .\ForegroundVsBackground.exe

> Prueba de ejecución:
Ejecución assembly ForegroundVsBackground.exe
Figura 2. Ejecución assembly ForegroundVsBackground.exe.
3.1.1.2 Aplicación WinForms

Creemos una aplicación basado en WinForms para demostrar y resaltar diferencia entre un thread foreground y uno background:

En este código podemos resaltar las siguientes líneas de código:
  • Línea 75: creación del thread t asociado al método Retraso
  • Línea 76: este thread corresponderá al plano background:

    t.IsBackground = true;
  • Línea 86: creación del thread t asociado al método Retraso.
  • Línea 87: este thread es de primer plano (foreground):

    t.IsBackground = false;
Las líneas restantes corresponden con elementos de programa para la construcción de la interfaz gráfica que se muestra en la Figura 3.
GUI de la aplicación Foreground vs Background Thread
Figura 3. GUI de la aplicación Foreground vs Background Thread.
Compilación:

  1. csc /target:winexe ForegroundVsBackgroundWinForms.cs

Ejecución assembly:

  1. .\ForegroundVsBackgroundWinForms.exe

> Prueba de ejecución:
Ejecución assembly ForegroundVsBackgroundWinForms.exe
Figura 4. Ejecución assembly ForegroundVsBackgroundWinForms.exe.

4. Práctica: Código C#

«¿Más código C#? Sí»

Creemos otro ejemplo para afianzar los conceptos de la sección anterior. Esta vez se trata de una aplicación basada en consola que pone en prueba dos threads: uno en primer plano y el otro en segundo plano. Cada uno realiza una determina cada cantidad de iteraciones dentro de un ciclo for.

En la línea 14 creamos un thread usando el delegado ParameterizedThreadStart, el cual encapsula al método ContadorNumeros. Esto nos va a permitir invocar a este método con el número de interaciones a realizar en el ciclo for de la líneas 35-43. De manera análoga, para el thread que se crea en la línea 18. Aunque este último se ejecutará en segundo plano:

t2.IsBackground = true;

Compilación:


  1. csc /target:exe IteracionesThreads.cs

Ejecución assembly:


  1. .\IteracionesThreads.exe

> Prueba de ejecución (ideone.com).

> Prueba de ejecución (local):
Ejecución assembly IteracionesThreads.exe
Figura 5. Ejecución assembly IteracionesThreads.exe.

Vale observar que en la Figura 5 el thread t2 no continua mostrando las iteraciones restantes; debido a que se trata de un thread background.

5. Artefactos

Enlaces de descarga de los artefactos producidos durante el desarrollo de esta receta:

6. Conclusiones

Hemos comprendido la diferencia entre un thread foreground y background. Esto lo logramos creando diferentes aplicaciones (consola y WinForms): desde estas aplicaciones creamos threads especificando el valor true (background) o false (foreground [valor por defecto]) a la propiedad IsBackground de la clase Thread.

7. Glosario

  • Background
  • Foreground
  • Plano
  • Primer plano
  • Segundo plano
  • Thread

8. Literatura & Enlaces

[1]: Multithreading in C# 5.0 Cookbook by Eugene Agafonov. Copyright 2013 Eugene Agafonov, 978-1-84969-764-4.
[2]: Foreground and Background Threads - http://msdn.microsoft.com/en-us/library/h339syd0%28v=vs.110%29.aspx
[3]: What is Background & Foreground thread - http://social.msdn.microsoft.com/Forums/vstudio/en-US/700ab651-8d20-421d-ab87-9a7e96a5d774/what-is-background-foreground-thread?forum=csharpgeneral
[4]: What is Foreground or Background Thread - http://www.c-sharpcorner.com/uploadfile/40e97e/what-is-foreground-or-background-thread/
[5]: How Threads and Foreground & Background Threads Work in C# .NET - http://www.c-sharpcorner.com/UploadFile/ff0d0f/working-of-thread-and-foreground-background-thread-in-C-Sharp730/
[6]: Receta No. 3-9 en C#: Descarga de Assemblies y Dominios de Aplicación | OrtizOLón Software (xCSw) - http://ortizol.blogspot.com/2014/06/receta-no-3-9-en-csharp-descarga-de-assemblies-y-dominios-de-aplicacion.html
[7]: Receta Multithreading en C# No. 1-4: Abortar un Thread en Ejecución | OrtizOLón Software (xCSw) - http://ortizol.blogspot.com/2014/06/receta-multithreading-en-csharp-no-1-4-abortar-un-thread-en-ejecucion.html
[8]: Thread.IsBackground Property (System.Threading) - http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground%28v=vs.110%29.aspx


J

No hay comentarios:

Publicar un comentario

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