Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. using System;
  2. using System.Threading;
  3. using System.Collections.Generic;
  4.  
  5. namespace Recetas.CSharp.Cap04.R0407
  6. {
  7.     public sealed class SincronizacionConsola
  8.     {
  9.         // Objeto bloqueador para sincronización:
  10.         private static object lockerConsola = new object();
  11.        
  12.         // Cola para las tareas a ejecutar:
  13.         private static Queue<string> colaTareas =
  14.             new Queue<string> ();
  15.        
  16.         // Valor bandera para indicar la continuación o
  17.         // fin del procesamiento de tares:
  18.         private static bool procesarMas = true;
  19.        
  20.         // Método utilitario para mostrar información del
  21.         // thread en ejecución:
  22.         private static void MostrarInfoThread (string mensaje)
  23.         {
  24.             lock (lockerConsola)
  25.             {
  26.                 Console.WriteLine ("[{0,3}/{1}] - {2} : {3}",
  27.                     Thread.CurrentThread.ManagedThreadId,
  28.                     Thread.CurrentThread.IsThreadPoolThread ? "pool" : "primer plano",
  29.                     DateTime.Now.ToString ("HH:mm:ss.ffff"), mensaje
  30.                 );
  31.             }
  32.         }
  33.        
  34.         // Método que ejecutará cada thread para procesar los elementos
  35.         // en la cola `colaTareas`:
  36.         private static void ProcesarTareasCola()
  37.         {
  38.             // Representa uno de los de la cola:
  39.             string elementoCola = null;
  40.            
  41.             MostrarInfoThread ("El thread ha iniciado. Procesando elementos...");
  42.            
  43.             // Mientras que valor bandera `procesarMas` sea verdadero, es decir
  44.             // mientras que no se haya emitido la señal de terminación
  45.             // continuar el procesamiento de los elementos de la cola `colaTareas`:
  46.             while (procesarMas)
  47.             {
  48.                 // Entra en región crítica:
  49.                 Monitor.Enter (colaTareas);
  50.                
  51.                 try
  52.                 {
  53.                     // Extrae un elemento de la cola, y espera por el siguiente
  54.                     // (si hay uno disponible:
  55.                     if (colaTareas.Count == 0)
  56.                     {
  57.                         MostrarInfoThread ("No hay elementos en la cola, en espera...");
  58.                        
  59.                         // Espera hasta que se invoce el método Pulse
  60.                         // con colaTareas:
  61.                         Monitor.Wait (colaTareas);
  62.                     }
  63.                     else
  64.                     {
  65.                         // Obtención del siguiente elemento de la cola:
  66.                         elementoCola = colaTareas.Dequeue();
  67.                     }
  68.                 }
  69.                 finally
  70.                 {
  71.                     // Libera el bloque sobre la región crítica:
  72.                     Monitor.Exit (colaTareas);
  73.                 }
  74.                
  75.                 // Procesa otro elemento de cola si existe:
  76.                 if (elementoCola != null)
  77.                 {
  78.                     // Bloque el acceso a la consola y muestra una serie de
  79.                     // mensajes:
  80.                     lock (lockerConsola)
  81.                     {
  82.                         for (int i = 0; i < 5; ++i)
  83.                         {
  84.                             MostrarInfoThread ("Procesando: " + elementoCola);
  85.                             Thread.Sleep (200);
  86.                         }
  87.                     }
  88.                    
  89.                     // Reestablece el valor por defecto de elementoCola:
  90.                     elementoCola = null;
  91.                 }
  92.             }
  93.            
  94.             // Cuando ya no hay más elementos a procesar:
  95.             MostrarInfoThread ("Finalizando...");
  96.         }
  97.        
  98.         public static void Main()
  99.         {
  100.             MostrarInfoThread ("Inicio de creación de threads...");
  101.            
  102.             // Agregación de un elemento a la cola de tareas:
  103.             lock (colaTareas)
  104.             {
  105.                 colaTareas.Enqueue ("Tarea No. 1");
  106.             }
  107.            
  108.             // Crea e inicia 3 threads para la ejecución
  109.             // del método ProcesarTareasCola:
  110.             for (int i = 1; i <= 3; ++i)
  111.             {
  112.                 (new Thread(ProcesarTareasCola)).Start();
  113.             }
  114.            
  115.             Thread.Sleep (1500);
  116.            
  117.             /// Cuando el usuario presione la tecla Enter,
  118.             // se agrega una tarea y se activa un thread
  119.             // para procesarla:
  120.             MostrarInfoThread ("Presione Enter para activar un thread en espera.");
  121.             Console.ReadLine ();
  122.            
  123.             // Agrega otro elemento a la cola de tareas:
  124.             lock (colaTareas)
  125.             {
  126.                 // Agrega una nueva tarea:
  127.                 colaTareas.Enqueue ("Tarea No. 2");
  128.                
  129.                 // Activa un thread en espera:
  130.                 Monitor.Pulse (colaTareas);
  131.             }
  132.            
  133.             Thread.Sleep (2000);
  134.            
  135.             // Cuando el usuario presione Enter se agregan
  136.             // 3 tareas a la cola, y se activan 3 threads
  137.             // para procesarlas:
  138.             MostrarInfoThread ("Presione Enter para activar 3 threas en espera.");
  139.             Console.ReadLine ();
  140.            
  141.             // Agreaga otros tres elementos a la cola y
  142.             // activa su procesamiento:
  143.             lock (colaTareas)
  144.             {
  145.                 colaTareas.Enqueue ("Tarea No. 3");
  146.                 Monitor.Pulse (colaTareas);
  147.                 colaTareas.Enqueue ("Tarea No. 4");
  148.                 Monitor.Pulse (colaTareas);
  149.                 colaTareas.Enqueue ("Tarea No. 5");
  150.                 Monitor.Pulse (colaTareas);
  151.             }
  152.            
  153.             Thread.Sleep (3500);
  154.            
  155.             // Cuando el usuario presione Enter, se emite una señal
  156.             // para para terminar todas las tareas:
  157.             MostrarInfoThread ("Presione Enter para procesar todas las tareas.");
  158.             Console.ReadLine ();
  159.            
  160.             // Finaliza la cola de espera:
  161.             lock (colaTareas)
  162.             {
  163.                 // Emite la señal para la finalziación de los
  164.                 // threads:
  165.                 procesarMas = false;
  166.                
  167.                 Monitor.PulseAll (colaTareas);
  168.             }
  169.            
  170.             Thread.Sleep (1000);
  171.            
  172.             // Finalización:
  173.             MostrarInfoThread ("El método Main finalizó. Presione Enter.");
  174.             Console.ReadLine ();
  175.         }
  176.     }
  177. }