Índice
1. Introducción2. Palabras Clave
3. Problema
4. Solución
5. Discusión de la Solución
5.1 Clase Task
5.2 Método ContinueWith
5.3 Enumeración TaskContinuationOptions
5.4 Enumeración TaskCreationOptions
6. Práctica: Combinación de Tareas con Task
7. Conclusiones
8. Literatura & Enlaces
1. Introducción
Una nueva receta multithreading en C# para comprender cómo combinar dos o más tareas. La combinación de tareas puede resultar útil para la ejecución de procesos de dependencia jerárquica. La relación de dependencia se análoga con la jerarquía padre-hijo: mientras que una tarea finaliza su ejecución otra espera una señal de continuación para terminar con el ciclo de ejecución de un proceso.
2. Palabras Clave
- Tarea
- Tarea de continuación
- Thread
3. Problema
Combinar dos o más tareas con dependencia en el orden de ejecución.
4. Solución
La clase Task cuenta con métodos para establecer una relación de jerarquía de ejecución entre tareas: permite combinar una tarea que dependa de otra en la ejecución de un proceso.
5. Discusión de la Solución
5.1 Clase Task
[Nota: Ver sección 5.1 de Receta Multithreading en C# No. 4-1: Cómo Crear una Tarea para conocer los esenciales de la clase Task.]
5.2 Método ContinueWith()
El método TaskContinueWith ("Task.ContinueWith Method", 2016) crea una tarea para ser ejecutada una vez finalizada la ejecución de otro proceso.
5.3 Enumeración TaskContinuationOptions
Con la enumeración TaskContinuationOptions ("TaskContinuationOptions Enumeration", 2016) se especifica el comportamiento para una tarea que se crea a partir de la invocación de TaskContinueWith.
5.4 Enumeración TaskCreationOptions
La enumeración TaskCreationOptions ("TaskCreationOptions Enumeration", 2016) permite especificar parámetros para la creación y ejecución de objetos Task.
6. Práctica: Combinación de Tareas con Task
En este ejemplo de código C# se presenta cómo combinar dos objetos Task a través del uso del método ContinueWith.
En las líneas 12 y 13 se crean dos objetos Task para la ejecución asincrónica del método Proceso() (líneas 96-107). Luego se invoca el método ContinueWith sobre el objeto tareaNo1 para crear una tarea de continuación al finalizar tareaNo1: muestra el valor entero retornado por la ejecución asincrónica de Proceso().
Al invocar Start sobre tareaNo1 y tareaNo2 se inicia la ejecución asincrónica del método Proceso() en threads de ejecución distintos. Para lograr que la ejecución tenga efecto en la salida estándar de la consola, con el método Sleep (línea 31) se suspende la continuación de ejecución de Main.
Sobre las líneas 35-49 ocurren las siguientes acciones:
- Líneas 35-42: crea un objeto Task de continuación para que una vez finalice la ejecución de tareaNo2 se muestre el valor calculado con t.Result.
- Líneas 45-49: cuando el objeto Task que se creó en la línea 35 finalice su ejecución se muestra en la salida estándar el estado final de ejecución de la tarea de ejecución.
De nuevo con el método static Sleep se detiene la ejecución de Main hasta por dos segundos.
Para una demostración final de la dependencia jerárquica de ejecución de tareas, se crea otro objeto Task con tareas anidadas:
- Líneas 60-63: tarea para ejecución anidada. Finalizada su ejecución se continua con la tarea padre -tareaNo3-.
- Línea 66-68: tarea de continuación para tareaAnidada (línea 60).
El ciclo while (líneas 77-85) comprueba el estado de ejecución de tareaNo3. Por cada ciclo se imprime el estado de ejecución general. Los estados dependen de la ejecución de tareaAnidada y la tarea de continuación. Antes de terminar la ejecución de esta aplicación de prueba, se imprime el estado de ejecución final de tareaNo3.
Compilación:
csc /t:exe CombinacionTareas.cs
Ejecución assembly:
.\CombinacionTareas.exe
Demostración ejecución assembly (ideone.com): http://ideone.com/t61HU5
7. Conclusiones
Se ha comprendido el proceso de combinación de tareas usando diferentes enfoques: tareas de continuación y tareas anidadas. Estos mecanismos son relativamente sencillos y naturales respecto a las soluciones -recetas- presentadas en los capítulos 3 y 4: sincronización de threads y uso de pool de threads. Se notó además cómo parametrizar la ejecución de una tarea anidada y de continuación: modo sincrónico, por ejemplo.
La próxima receta multithreading demuestra cómo convertir una implementación en Asynchronous Programming Model (APM) al modelo de tareas.
8. Literatura & Enlaces
Agafonov, E. (2013). Multithreading in C# 5.0 Cookbook. United States: Packt Publishing.Receta Multithreading en C# No. 4-1: Cómo Crear una Tarea (2016, abril 22). Recuperado desde: http://ortizol.blogspot.com.co/2016/03/receta-multithreading-en-csharp-no-4-1-como-crear-una-tarea.html
Task.ContinueWith Method (Action(Task)) (System.Threading.Tasks) (2016, abril 22). Recuperado desde: https://msdn.microsoft.com/en-us/library/dd270696(v=vs.110).aspx
Task.GetAwaiter Method (System.Threading.Tasks) (2016, abril 22). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.threading.tasks.task.getawaiter(v=vs.110).aspx
TaskContinuationOptions Enumeration (System.Threading.Tasks) (2016, abril 22). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions(v=vs.110).aspx
TaskCreationOptions Enumeration (System.Threading.Tasks) (2016, abril 22). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcreationoptions(v=vs.110).aspx
V