Invocar delegados anónimos asíncronamente (o como usar el pool de hilos en dos líneas de código)

Una de las características mas interesantes de los delegados es que pueden ser invocados de manera asíncrona. La pega de los delegados es que hay que declararlos, y hacer una función para asignarla al delegado y luego ya podremos hacer la invocación asíncrona. Las ventajas de la invocación asíncrona respecto a crear un hilo explicitamente son varias: menor cantidad de código y sobre todo, que el hilo será un hilo de pool de hilos de .Net, con las ventajas para el rendimiento que esto lleva asociadas.


Muchas veces usamos delegados asícronos para dotar de asincronía a un método síncrono, pero el problema es que tenemos que crear toda la artilleria de un delegado. Una pega aparejada es que a las complejidades propias de la programación asíncrona, uniremos la menor legibilidad (los delegados son muy útiles pero no son precisamente legibles).


La solución pasa por usar un delegado anónimo de manera que podemos poner en línea el código que se ejecutará en otro hilo. El truco del almendruco es simplemente asignar el delegado anónimo a un tipo de delegado ThreadStart. Además esta técnica nos permite saber de manera muy sencilla, usando un delegado AsyncCallback y poniedolo en el primer parámetro de la llamada a BeginInvoke, cuando el hilo levantado ha teerminado su trabajo. Podemos usar el segundo parámetro del método BeginInvoke del delegado de tipo ThreadStart para pasar estado al delegado que se ejdutará cuando el hilo termine. Si no necesitamos ninguna de estas características podríamos pasar a null ambos argumentos.


Sin duda, una manera curiosa y útil en ocasiones de usar el pool de hilos.


Creo que con el siguiente código el asunto quedará claro:




using System;


using System.Threading;


 


namespace SimpleThreadStart


{


  class Program


  {


    static void Main(string[] args)


    {


      ThreadStart ts =


        delegate


        {


          Console.WriteLine(“Los delegados anónimos son mágicos”);


        };


 


      ts.BeginInvoke(ThreadCompleted, “ESTAD0”);


 


      //Dar tiempo a que el hilo haga su trabajo…


      Console.WriteLine(“Pulse una tecla para terminar…”);


      Console.ReadKey();


    }


 


    //Esta función se ejecuta cuando el hilo termina su trabajo.


    static private void ThreadCompleted(IAsyncResult ar)


    {


      Console.WriteLine(“Se completo el hilo creado mediante un delegado asincrono”);


      Console.WriteLine(“El estado pasado fue {0}”, (string)ar.AsyncState);


    }


  }


}


Espero que os resulte útil o al menos curioso.

6 comentarios en “Invocar delegados anónimos asíncronamente (o como usar el pool de hilos en dos líneas de código)”

  1. Hola Rodrigo!
    El ejemplo es muy claro…pero te lanzo una pregunta, ¿Esta forma de utilizar delegados anónimos es válida también en C# 3.0? ¿O se podría hacer de otra forma aprovechando las expresiones lambda?

    Un abrazo crack

    JC’s

  2. JC todo delegado se puede convertir en expresión lambda. Lo anterior quedaría como:

    ThreadStart ts = () => Console.WriteLine(“Las expresiones lambda no son mágicas, son pura lógica”);

  3. @Unai: Interesante artículo, gracias por el aporte titán!!!

    @JC y Anonimo: Como bien dice anónimo todo delegado se puede expresar como una lambda, no lo hice así porque el código en el que usé esa técnica es C# 2.0, pero sin duda aun queda más reducido. Gracias a los dos a uno por la idea y al otro por la solución.

    Un saludo!!!

  4. ¿Pueden implantarse delegados en WCF? Lo pregunto porque es algo que no he visto y estoy diseñando un pool de objetos y ya tuve problemas con dynamic al consumir el servicio.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *