fork download
  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. }
Success #stdin #stdout 0.05s 37128KB
stdin
Standard input is empty
stdout
[  1/primer plano] - 01:55:26.0279 : Inicio de creación de threads...
[  3/primer plano] - 01:55:26.0644 : El thread ha iniciado. Procesando elementos...
[  4/primer plano] - 01:55:26.0647 : El thread ha iniciado. Procesando elementos...
[  3/primer plano] - 01:55:26.0651 : Procesando: Tarea No. 1
[  3/primer plano] - 01:55:26.2653 : Procesando: Tarea No. 1
[  3/primer plano] - 01:55:26.4654 : Procesando: Tarea No. 1
[  3/primer plano] - 01:55:26.6655 : Procesando: Tarea No. 1
[  3/primer plano] - 01:55:26.8656 : Procesando: Tarea No. 1
[  4/primer plano] - 01:55:27.0657 : No hay elementos en la cola, en espera...
[  5/primer plano] - 01:55:27.0662 : El thread ha iniciado. Procesando elementos...
[  3/primer plano] - 01:55:27.0663 : No hay elementos en la cola, en espera...
[  5/primer plano] - 01:55:27.0663 : No hay elementos en la cola, en espera...
[  1/primer plano] - 01:55:27.5654 : Presione Enter para activar un thread en espera.
[  4/primer plano] - 01:55:27.5676 : Procesando: Tarea No. 2
[  4/primer plano] - 01:55:27.7677 : Procesando: Tarea No. 2
[  4/primer plano] - 01:55:27.9678 : Procesando: Tarea No. 2
[  4/primer plano] - 01:55:28.1679 : Procesando: Tarea No. 2
[  4/primer plano] - 01:55:28.3680 : Procesando: Tarea No. 2
[  4/primer plano] - 01:55:28.5680 : No hay elementos en la cola, en espera...
[  1/primer plano] - 01:55:29.5676 : Presione Enter para activar 3 threas en espera.
[  3/primer plano] - 01:55:29.5677 : Procesando: Tarea No. 3
[  3/primer plano] - 01:55:29.7679 : Procesando: Tarea No. 3
[  3/primer plano] - 01:55:29.9679 : Procesando: Tarea No. 3
[  3/primer plano] - 01:55:30.1684 : Procesando: Tarea No. 3
[  3/primer plano] - 01:55:30.3686 : Procesando: Tarea No. 3
[  3/primer plano] - 01:55:30.5687 : No hay elementos en la cola, en espera...
[  5/primer plano] - 01:55:30.5688 : Procesando: Tarea No. 4
[  5/primer plano] - 01:55:30.7689 : Procesando: Tarea No. 4
[  5/primer plano] - 01:55:30.9690 : Procesando: Tarea No. 4
[  5/primer plano] - 01:55:31.1691 : Procesando: Tarea No. 4
[  5/primer plano] - 01:55:31.3692 : Procesando: Tarea No. 4
[  5/primer plano] - 01:55:31.5693 : No hay elementos en la cola, en espera...
[  4/primer plano] - 01:55:31.5693 : Procesando: Tarea No. 5
[  4/primer plano] - 01:55:31.7694 : Procesando: Tarea No. 5
[  4/primer plano] - 01:55:31.9695 : Procesando: Tarea No. 5
[  4/primer plano] - 01:55:32.1696 : Procesando: Tarea No. 5
[  4/primer plano] - 01:55:32.3696 : Procesando: Tarea No. 5
[  4/primer plano] - 01:55:32.5697 : No hay elementos en la cola, en espera...
[  1/primer plano] - 01:55:33.0681 : Presione Enter para procesar todas las tareas.
[  5/primer plano] - 01:55:33.0684 : Finalizando...
[  4/primer plano] - 01:55:33.0686 : Finalizando...
[  3/primer plano] - 01:55:33.0687 : Finalizando...
[  1/primer plano] - 01:55:34.0684 : El método Main finalizó. Presione Enter.