C Sharp (C#) – Usar Delegados – Parte 7

Hacer llamadas asíncronas usando delegados

Hasta el momento hemos hecho llamadas a métodos de forma síncrona por medio de delegados.dos caminos

¿Qué son las llamadas síncrona? Las llamadas a métodos de forma síncrona son las que siguen el patrón común de los programas de pasar a la próxima instrucción cuando se termine de ejecutar un método. Cuando se ejecuta un método se espera a que se termine la ejecución para pasar a la siguiente instrucción, se espera a que se terminen las instrucciones del método para pasar a la siguiente. Estas son las llamadas a métodos de forma síncrona, son las llamadas a métodos que se ocupan comúnmente.

¿Qué son las llamadas asíncronas? En las llamadas a métodos de forma asíncrona no se espera a que se termine la llamada para pasar a la siguiente instrucción, sino que el programa sigue pasando ordenadamente a la siguientes instrucciones sin esperar a que se termine la llamada. Una llamada asíncrona queda en una especie de hilo de ejecución aparte.

Una de las utilidades de las llamadas asíncronas es evitar que las aplicación principal se congele ya que se puede enviar una tarea pesada a que se ejecute de manera asíncrona (en un hilo de ejecución a parte). Con esto se evita a que la ejecución del programa principal se congele mientras hace una tarea pesada.

Se pueden hacer llamadas asíncronas por medio de delegados. Pero este mecanismo tiene una limitación, es que solo es valido para objetos delegados que almacenen un único método, el -objeto delegado síncrona- debe referenciar un solo método, de lo contrario dará un excepción System.ArgumentExceptión . Pero el objeto delegado que va a ser asíncrono puede referenciar a más de un método.  C Sharp cuenta con algunas clases, interfaces, delegados, etc. predefinidas en el espacio de nombres System para manejar las llamadas síncronas y asíncronas.

Tenemos un delegado, con el cual podemos crear un objeto delegado que puede almacenar un método que se quiere que sea asíncrono. El delegado es:

public delegate void AsyncCallback (IAsyncResult ar)

Tenemos una interfaz, la cual almacena información relativa al método que será llamado de forma asíncrona.

public interface System.IAsyncResult

Y tenemos dos métodos BeginInvoke y EndInvoke, que tienen todos los objetos delegados. BeginInvoke nos sirve para invocar el objeto delegado que referencia a un método síncronos y a la vez invocar un objeto delegado que referencia uno o más métodos de forma asíncrona.

IAsyncResult BeginInvoke (<parámetros>, AsyncCallback cb, Object o)

Como vemos el método ‘BeginInvoke’ devuelve un objeto ‘IAsyncResult’ que contiene información relacionada al resultado de la ejecución de los métodos asíncrona, lo veremos en el ejemplo. En ‘<parámetros>’ esta relacionado con los parámetros del tipo delegado al cual se llama con ‘BeginInvoke’. En ‘Object o’ van un objeto opcional que se le quisiera pasar a los métodos que se ejecutan de manera asíncrona.

<tipoRetorno> EndInvoke (<parámetrosRefOut>, IASyncResult ar)

El método ‘EnInvoke’ sirve para recibir el valor de retorno de los métodos que fueron llamados de manera asíncrona, para saber las excepciones (si es que hubieron). Luego veremos más.

Ahora el ejemplo:

// por Writkas
//
// Delegados5_Comentado.cs : Hacer llamadas asíncronas usando delegados
//
// Compilar en Linux con Mono:
//	gmcs Delegados5_Comentado.cs
//
// Compilar en Linux con Mono en C# 5:
//	gmcs -langversion:future Delegados5_Comentado.cs
//
// Ejecutar:
//	mono Delegados5_comentado.exe

// Recordar que en el namespace System están definidos todos las clases para el
// tratamiento de las llamadas asíncrona y también síncrona.
using System;

// Creamos un tipo delegado común y corriente
delegate void DelegadoAsíncronas (string str);

class Test
{
  public static void Main ()
  {
  // Creamos un objeto delegado común 'objDA' y le asignamos el método 'Método'
    DelegadoAsíncronas objDA = new DelegadoAsíncronas (Método1);
  // El objeto 'objDA' solo debe contener un solo método almacenado si luego se quiere
  // hacer una llamada asíncrona.

  // Se crea un objeto 'AsyncCallback' y se le añade un método 'Método2', para luego
  // enviarle este objeto con su método referenciado al objeto delegado 'objDA' que creamos
  // anteriormente.
  // A continuación se indica que es AsyncCallvack :
  // public delegate void AsyncCallback (IAsyncResult ar)
    AsyncCallback objAC = new AsyncCallback (Método2);

  // Almacena información relativa al método que será llamado de forma asíncrona:
  // public interface System.IAsyncResult
  // Se puede saber si el método asíncrona se termino de ejecutar con la propiedad:
  // public  bool IsCompleted [solo lectura]
  // Se puede saber si el método asíncrona se terminó de ejecutar de manera sícrona con:
  // public bool CompletedSyncronously [solo lectura]
    IAsyncResult objIAR;

  // Lanza la llamada al 'Método2' que está contenida en el objeto delegado 'objAC' de
  // manera asíncrona. el 'Método2' se ejecuta de manera asíncrona (en un hilo de ejecución
  // a parte), pero el método que referencia 'objDA' se ejecuta de manera síncrona.
  // 'IAsyncResult' almacenará información relacionada a ese hilo :
  // IAsyncResult BeginInvoke (, AsyncCallback cb, Object o)
  // En  van los parámetros del típo delegado.
    objIAR = objDA.BeginInvoke ("Hola", objAC, "Hola2");
  // 'objAC' contiene el o los métodos que se quiere que sean asíncronos. '"Hola2"' es
  // un argumento opcional que se le puede enviar a los métodos a ejecutar de forma
  // asíncrona. Es opcional, puede ir tanto '"Hola2"' como 'null'.

  // Cuando se ejecuta el método EndInvoke se muestran los resultados de los métodos
  // llamados, las excepciones que hubieron (si es que hubieron), etc.
  //  EndInvoke (, IASyncResult ar)
    objDA.EndInvoke (objIAR);

  // Si se terminó de ejecutar el hilo o no
    if (objIAR.IsCompleted)
      Console.WriteLine ("Se termino la llamada asíncrona");
    else
      Console.WriteLine ("Aún no termina la llamada asíncrona");

  // Si se terminó de ejecutar el hilo de manera síncrona. Se usa, ya que puede que
  // existan excepciones de las cuales no se informe. Pero esas excepciones se
  // informarán si se utiliza el método EndInvoque.
    if (objIAR.CompletedSynchronously)
      Console.WriteLine ("El hilo se termino de forma síncrona");
  // Si se termino de ejecutar el hilo de manera asíncrona
    else if (objIAR.CompletedSynchronously == false)
      Console.WriteLine ("El hilo se termino de forma asíncrona");

  // Espera a que se presione una tecla
    Console.Read ();
  }

  public static void Método1 (string str)
  {
    Console.WriteLine ("Desde Método1: {0}",str);
  }

  public static void Método2 (IAsyncResult obj)
  {
  // Se obtiene el objeto proporcionado al empezar la ejecución de la operación asíncrona :
  // public object AsyncState [solo lectura]
    Console.WriteLine ("Desde Método2: {0}", obj.AsyncState);
  }
}

La salida:

writkas@linux-xag2:~/Programacion/C#> gmcs -langversion:future Delegados5_Comentado.cs
writkas@linux-xag2:~/Programacion/C#> mono Delegados5_Comentado.exe
Desde Método1: Hola
Desde Método2: Hola2
Se termino la llamada asíncrona
El hilo se termino de forma asíncrona

writkas@linux-xag2:~/Programacion/C#>

Aquí puedes descargar los ejemplos de Delegados en C Sharp que hemos visto hasta ahora.

logo descargar

Este artículo es una parte más de una serie de artículos que trata de explicar el como usar delegados. Hasta el momento estos son los artículos ->

  1. C Sharp (C#) – Usar delegados – Ejemplo mínimo sobre delegados
  2. C Sharp (C#) – Usar delegados – Añadir y quitar métodos a un objeto delegado
  3. C Sharp (C#) – Usar delegados – ¿Cuándo se ocupan los delegados?
  4. C Sharp (C#) – Usar delegados – Acceso a miembros de delegados, añadir y quitar métodos y un ejercicio para entender los delegados en C Sharp
  5. C Sharp (C#) – Usar delegados – Usar delegados para facilitar el uso de eventos
  6. C Sharp (C#) – Usar delegados – Manejar listas de métodos que referencian los objetos delegados

.

(Parte 6: Manejar listas de métodos que referencian los objetos delegados) Artículo anterior | Artículo siguiente (Parte 7: —)