Created
June 15, 2014 00:39
-
-
Save Fhernd/4099b4bfc6616fbaaf0c to your computer and use it in GitHub Desktop.
Demostración técnicas de control de completitud de métodos invocados asincrónicamente.
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; | |
namespace Recetas.Cap04 | |
{ | |
public sealed class TecnicasInvocacionAsincronica | |
{ | |
// Método utilitario para la presentación de datos | |
// de ejecución de los métodos con ejecución asincrónica: | |
private static void VisorDatos(DateTime hora, string mensaje) | |
{ | |
Console.WriteLine ("[{0,3}/{1}] - {2} : {3}", Thread.CurrentThread.ManagedThreadId, | |
Thread.CurrentThread.IsThreadPoolThread ? "pool" : "principal", | |
hora.ToString ("HH:mm:ss.ffff"), mensaje); | |
} | |
// Delegado para permitir la ejecución de métodos | |
// con la firma compatible: | |
public delegate DateTime AsyncMetodosDelegate(int retraso, string nombre); | |
// Método que simula la ejecución de una tarea que toma | |
// varios segundos: | |
public static DateTime ProcesoLargo (int retraso, string nombre) | |
{ | |
VisorDatos (DateTime.Now, String.Format ("{0} - thread en ejecución.")); | |
// Simula la ejecución de tareas que toman tiempo: | |
Thread.Sleep (retraso); | |
VisorDatos (DateTime.Now, String.Format ("{0} - thread finalizado.")); | |
return DateTime.Now; | |
} | |
// Aplicación del patrón (técnica) de determinación de completidud | |
// de invocación asincrónica `Blocking`: | |
public static void Blocking() | |
{ | |
Console.WriteLine ("\n === Aplicación Técnica Blocking === "); | |
// Creación y encapsulamiento con delegado: | |
AsyncMetodosDelegate procesoLargo = ProcesoLargo; | |
// Inicia la invocación asincrónica: | |
IAsyncResult asyncResult = procesoLargo.BeginInvoke (2000, "Blocking", null, null); | |
// Antes de que se realice el bloqueo se ejecutan estas instrucciones: | |
for (int i = 0; i < 3; ++i) | |
{ | |
VisorDatos (DateTime.Now, "Continua ejecutándose antes de bloquearse..."); | |
Thread.Sleep (200); | |
} | |
// Inicio de bloque: | |
VisorDatos (DateTime.Now, "Bloqueo hasta que se complete el método asincrónico."); | |
// Datos de completitud de método asincrónico: | |
DateTime completoEn = DateTime.MinValue; | |
try | |
{ | |
completoEn = procesoLargo.EndInvoke (asyncResult); | |
} | |
catch | |
{ | |
// Aquí se trata la excepción en caso de que ocurra... | |
} | |
// Informe final: | |
VisorDatos (completoEn, "Demostración técnica blocking finalizada"); | |
} | |
// Demostración del patrón (técnica) polling: | |
public static void Polling() | |
{ | |
Console.WriteLine ("\n === Aplicación Técnica Polling === "); | |
// Creación y encapsulamiento con delegado: | |
AsyncMetodosDelegate procesoLargo = ProcesoLargo; | |
// Inicia la invocación asincrónica: | |
IAsyncResult asyncResult = procesoLargo.BeginInvoke (2000, "Blocking", null, null); | |
// Mensaje de inicio de consulta: | |
VisorDatos (DateTime.Now, "La consulta se realiza mientras que el método asincrónico no haya finalizado"); | |
while (!asyncResult.IsCompleted) | |
{ | |
VisorDatos (DateTime.Now, "Polling..."); | |
Thread.Sleep (300); | |
} | |
// Datos de completitud de método asincrónico: | |
DateTime completoEn = DateTime.MinValue; | |
try | |
{ | |
completoEn = procesoLargo.EndInvoke (asyncResult); | |
} | |
catch | |
{ | |
// Aquí se trata la excepción en caso de que ocurra... | |
} | |
// Informe final: | |
VisorDatos (completoEn, "Demostración técnica polling finalizada"); | |
} | |
// Demostración del patrón (técnica) Waiting: | |
public static void Waiting() | |
{ | |
Console.WriteLine ("\n === Aplicación Técnica Waiting === "); | |
// Creación y encapsulamiento con delegado: | |
AsyncMetodosDelegate procesoLargo = ProcesoLargo; | |
// Inicia la invocación asincrónica: | |
IAsyncResult asyncResult = procesoLargo.BeginInvoke (2000, "Blocking", null, null); | |
// Mensaje de inicio de consulta: | |
VisorDatos (DateTime.Now, "No se continua hasta que finalice el método asincrónico..."); | |
while (!asyncResult.AsyncWaitHandle.WaitOne(300, false)) | |
{ | |
VisorDatos (DateTime.Now, "La espera superó los 300ms..."); | |
} | |
// Datos de completitud de método asincrónico: | |
DateTime completoEn = DateTime.MinValue; | |
} | |
// Invocación del método ProcesoLargo múltiples veces: | |
public static void WaitAll() | |
{ | |
Console.WriteLine ("\n === Demostración WaitAll === "); | |
// Creación y encapsulamiento con delegado: | |
AsyncMetodosDelegate procesoLargo = ProcesoLargo; | |
// Arreglo para mantener instancias IAsyncResult para cada | |
// uno de los métodos que se invocan asincrónicamente: | |
ArrayList asyncResultados = new ArrayList(3); | |
// Agrega tres instancias de IAsyncResult: | |
asyncResultados.Add (procesoLargo.BeginInvoke (3000, "WaitAll 1", null, null)); | |
asyncResultados.Add (procesoLargo.BeginInvoke (2500, "WaitAll 2", null, null)); | |
asyncResultados.Add (procesoLargo.BeginInvoke (1500, "WaitAll 3", null, null)); | |
// Arreglo de objetos WaitHandle: | |
WaitHandle[] waitHandles = new WaitHandle[3]; | |
for (int i = 0; i < 3; ++i) | |
{ | |
waitHandles[i] = ((IAsyncResult)asyncResultados[i]).AsyncWaitHandle; | |
} | |
// Espera a que todos los métodos asincrónicos finalicen: | |
VisorDatos (DateTime.Now, "Esperando a que los tres métodos finalicen..."); | |
while (!WaitHandle.WaitAll(waitHandles, 300, false)) | |
{ | |
VisorDatos (DateTime.Now, "La espera superó los 300ms..."); | |
} | |
// Datos de completitud de método asincrónico: | |
DateTime completoEn = DateTime.MinValue; | |
foreach (IAsyncResult resultado in asyncResultados) | |
{ | |
try | |
{ | |
DateTime hora = procesoLargo.EndInvoke (resultado); | |
if (hora > completoEn) | |
{ | |
completoEn = hora; | |
} | |
} | |
catch | |
{ | |
// Aquí se trata la excepción en caso de que ocurra... | |
} | |
} | |
// Informe final: | |
VisorDatos (completoEn, "Demostración técnica WaitAll finalizada"); | |
} | |
// Demostración Callcack: | |
public static void Callback() | |
{ | |
Console.WriteLine ("\n === Demostración Callback === "); | |
// Creación y encapsulamiento con delegado: | |
AsyncMetodosDelegate procesoLargo = ProcesoLargo; | |
IAsyncResult asyncResult = procesoLargo.BeginInvoke (2000, "Callback", CallbackHandler, procesoLargo); | |
// Continua con otras tareas: | |
for (int i = 0; i < 15; ++i) | |
{ | |
VisorDatos (DateTime.Now, "Continua la ejecución de tareas..."); | |
Thread.Sleep (200); | |
} | |
} | |
private static void CallbackHandler(IAsyncResult resultado) | |
{ | |
// Recupera la isntancia del delegado: | |
AsyncMetodosDelegate procesoLargo = (AsyncMetodosDelegate) resultado.AsyncState; | |
// Datos de completitud de método asincrónico: | |
DateTime completoEn = DateTime.MinValue; | |
try | |
{ | |
completoEn = procesoLargo.EndInvoke (resultado); | |
} | |
catch | |
{ | |
// Aquí se trata la excepción en caso de que ocurra... | |
} | |
// Informe final: | |
VisorDatos (completoEn, "Demostración técnica Callback finalizada"); | |
} | |
public static void Main() | |
{ | |
// Ejecución de cada técnica determinación de completitud de invocación asincrónica: | |
Blocking(); | |
Polling(); | |
Waiting(); | |
WaitAll(); | |
Callback(); | |
// Esperar a finalizar: | |
Console.WriteLine (Environment.NewLine); | |
Console.WriteLine ("El método Main ha finalizado. Presione la tecla Enter para finalizar."); | |
Console.ReadLine(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment