using System; using System.Threading; using System.Threading.Tasks; namespace Recetas.Multithreading.R0403 { public class CombinacionTareas { public static void Main() { // Creación de dos tareas para ejecutar el método Proceso: var tareaNo1 = new Task( () => Proceso("Tarea No. 1", 3)); var tareaNo2 = new Task( () => Proceso("Tarea No. 2", 2)); // Una vez terminada la ejecución de `tareaNo1`, se continua con la ejecución // de la expresión lambda de ContinueWith: tareaNo1.ContinueWith( t => Console.WriteLine ("Respuesta Tarea no. 1: {0}. ID Thread: {1}. ¿Thread de pool de threads?: {2}.", t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread), TaskContinuationOptions.OnlyOnRanToCompletion ); // Inicia la ejecución asincrónica de los objetos Task: tareaNo1.Start(); tareaNo2.Start(); // Detiene la ejecución del thread de `Main` // para dar tiempo de ejecución a los objetos Task: Thread.Sleep(TimeSpan.FromSeconds(4)); // Creación de tarea de continuación para responder a // la finalización de de la Tarea no. 2: Task continuacion = tareaNo2.ContinueWith( t => Console.WriteLine ("Respuesta Tarea no. 2: {0}. ID Thread: {1}. ¿Thread de pool de threads?: {2}.", t.Result, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously ); // Se ejecuta una vez que el objeto Task `tareaNo2` finalice: continuacion.GetAwaiter().OnCompleted( () => Console.WriteLine ("Tarea de continuación de tarea 2 se completó. ID thread: {0}. ¿Thread de pool de threads?: {1}", Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread) ); // Detiene la ejecución del thread de Main // para dar tiempo de ejecución a los objetos Task: Thread.Sleep(TimeSpan.FromSeconds(2)); Console.WriteLine (); // Crea otra tarea con dos tareas -una anidad y otra de continuación-: var tareaNo3 = new Task( () => { // Crea objeto Task anidado: var tareaAnidada = Task.Factory.StartNew(() => Proceso("Tarea no. 4", 5), TaskCreationOptions.AttachedToParent ); // Una vez se complete la tarea anidada continuar con: tareaAnidada.ContinueWith( t => Proceso("Tarea no. 5", 2), TaskContinuationOptions.AttachedToParent); return Proceso("Tarea no. 3", 2); }); // Ejecución Tarea no. 3: tareaNo3.Start(); // Mientras que la tarea no. 3 se esté ejecutando: while(!tareaNo3.IsCompleted) { // Muestra en la salida estándar el estado actual // de ejecución del objeto Task `taskNo3`: Console.WriteLine ("Estado ejecución Tarea no. 3: {0}", tareaNo3.Status); // Espera por ciclo: Thread.Sleep(TimeSpan.FromSeconds(0.5)); } Console.WriteLine ("\nÚltimo estado de Tarea no. 3: {0}.", tareaNo3.Status); // Espera en thread Main hasta de 10 segundos: Thread.Sleep(TimeSpan.FromSeconds(10)); Console.WriteLine (); } // Proceso asincrónico para objetos Task: public static int Proceso(string nombre, int segundos) { Console.WriteLine ("La {0} se está ejecutando en el ID de thread {1}. ¿Thread del pool de threads?: {2}.", nombre, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); // Espera simulada para este método de ejecución asincrónica: Thread.Sleep(TimeSpan.FromSeconds(segundos)); return 45 * segundos; } } }