Created
July 10, 2014 01:21
-
-
Save Fhernd/0ad40981a441666d2acc to your computer and use it in GitHub Desktop.
Demostración del uso de la clase Monitor para la sincronización del acceso a la consola.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
using System.Collections.Generic; | |
namespace Recetas.CSharp.Cap04.R0407 | |
{ | |
public sealed class SincronizacionConsola | |
{ | |
// Objeto bloqueador para sincronización: | |
private static object lockerConsola = new object(); | |
// Cola para las tareas a ejecutar: | |
private static Queue<string> colaTareas = | |
new Queue<string> (); | |
// Valor bandera para indicar la continuación o | |
// fin del procesamiento de tares: | |
private static bool procesarMas = true; | |
// Método utilitario para mostrar información del | |
// thread en ejecución: | |
private static void MostrarInfoThread (string mensaje) | |
{ | |
lock (lockerConsola) | |
{ | |
Console.WriteLine ("[{0,3}/{1}] - {2} : {3}", | |
Thread.CurrentThread.ManagedThreadId, | |
Thread.CurrentThread.IsThreadPoolThread ? "pool" : "primer plano", | |
DateTime.Now.ToString ("HH:mm:ss.ffff"), mensaje | |
); | |
} | |
} | |
// Método que ejecutará cada thread para procesar los elementos | |
// en la cola `colaTareas`: | |
private static void ProcesarTareasCola() | |
{ | |
// Representa uno de los de la cola: | |
string elementoCola = null; | |
MostrarInfoThread ("El thread ha iniciado. Procesando elementos..."); | |
// Mientras que valor bandera `procesarMas` sea verdadero, es decir | |
// mientras que no se haya emitido la señal de terminación | |
// continuar el procesamiento de los elementos de la cola `colaTareas`: | |
while (procesarMas) | |
{ | |
// Entra en región crítica: | |
Monitor.Enter (colaTareas); | |
try | |
{ | |
// Extrae un elemento de la cola, y espera por el siguiente | |
// (si hay uno disponible: | |
if (colaTareas.Count == 0) | |
{ | |
MostrarInfoThread ("No hay elementos en la cola, en espera..."); | |
// Espera hasta que se invoce el método Pulse | |
// con colaTareas: | |
Monitor.Wait (colaTareas); | |
} | |
else | |
{ | |
// Obtención del siguiente elemento de la cola: | |
elementoCola = colaTareas.Dequeue(); | |
} | |
} | |
finally | |
{ | |
// Libera el bloque sobre la región crítica: | |
Monitor.Exit (colaTareas); | |
} | |
// Procesa otro elemento de cola si existe: | |
if (elementoCola != null) | |
{ | |
// Bloque el acceso a la consola y muestra una serie de | |
// mensajes: | |
lock (lockerConsola) | |
{ | |
for (int i = 0; i < 5; ++i) | |
{ | |
MostrarInfoThread ("Procesando: " + elementoCola); | |
Thread.Sleep (200); | |
} | |
} | |
// Reestablece el valor por defecto de elementoCola: | |
elementoCola = null; | |
} | |
} | |
// Cuando ya no hay más elementos a procesar: | |
MostrarInfoThread ("Finalizando..."); | |
} | |
public static void Main() | |
{ | |
MostrarInfoThread ("Inicio de creación de threads..."); | |
// Agregación de un elemento a la cola de tareas: | |
lock (colaTareas) | |
{ | |
colaTareas.Enqueue ("Tarea No. 1"); | |
} | |
// Crea e inicia 3 threads para la ejecución | |
// del método ProcesarTareasCola: | |
for (int i = 1; i <= 3; ++i) | |
{ | |
(new Thread(ProcesarTareasCola)).Start(); | |
} | |
Thread.Sleep (1500); | |
/// Cuando el usuario presione la tecla Enter, | |
// se agrega una tarea y se activa un thread | |
// para procesarla: | |
MostrarInfoThread ("Presione Enter para activar un thread en espera."); | |
Console.ReadLine (); | |
// Agrega otro elemento a la cola de tareas: | |
lock (colaTareas) | |
{ | |
// Agrega una nueva tarea: | |
colaTareas.Enqueue ("Tarea No. 2"); | |
// Activa un thread en espera: | |
Monitor.Pulse (colaTareas); | |
} | |
Thread.Sleep (2000); | |
// Cuando el usuario presione Enter se agregan | |
// 3 tareas a la cola, y se activan 3 threads | |
// para procesarlas: | |
MostrarInfoThread ("Presione Enter para activar 3 threas en espera."); | |
Console.ReadLine (); | |
// Agreaga otros tres elementos a la cola y | |
// activa su procesamiento: | |
lock (colaTareas) | |
{ | |
colaTareas.Enqueue ("Tarea No. 3"); | |
Monitor.Pulse (colaTareas); | |
colaTareas.Enqueue ("Tarea No. 4"); | |
Monitor.Pulse (colaTareas); | |
colaTareas.Enqueue ("Tarea No. 5"); | |
Monitor.Pulse (colaTareas); | |
} | |
Thread.Sleep (3500); | |
// Cuando el usuario presione Enter, se emite una señal | |
// para para terminar todas las tareas: | |
MostrarInfoThread ("Presione Enter para procesar todas las tareas."); | |
Console.ReadLine (); | |
// Finaliza la cola de espera: | |
lock (colaTareas) | |
{ | |
// Emite la señal para la finalziación de los | |
// threads: | |
procesarMas = false; | |
Monitor.PulseAll (colaTareas); | |
} | |
Thread.Sleep (1000); | |
// Finalización: | |
MostrarInfoThread ("El método Main finalizó. Presione Enter."); | |
Console.ReadLine (); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment