Skip to content

Instantly share code, notes, and snippets.

@Fhernd
Created June 15, 2014 00:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Fhernd/4099b4bfc6616fbaaf0c to your computer and use it in GitHub Desktop.
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.
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