Pooling de llamadas asincronas

Hora de volver a trabajar… asi que toca quitarle el polvo al Visual Studio que tenia abandonado ya estos meses, la buena vida se acaba… xD

En determinadas ocasiones, necesitamos lanzar un cierto número de ejecuciones en paralelo y esperar a que terminen todas para devolver el resultado final. Existen diversas formas de hacerlo, y yo voy a poner la que, después de darle un par de vueltas… me parece la mejor y más sencilla, … se puede hacer aún mejor, pero no se si más sencilla… y no se si lo que se puede mejorar merece la pena en cuanto a la complejidad que añade.

Un ejemplo práctico, este método pertenece a una clase que estoy programando para realizar pruebas de estres y carga, la clase tiene una lista de clientes y cuando se ejecuta esta función ejecuta el delegado que se pasa como argumento en paralelo en todos los clientes a la vez, recolecta las excepciones capturadas y las devuelve como una lista. Por supuesto, tiene que esperar a que terminen todas las pruebas en paralelo para poder devolver la lista 😛

private List<Exception> test(Int32 Times, Int32 Interval, TestDlg_ Test)
{
    List<Exception> errors = new List<Exception>();
    List<IAsyncResult> working = new List<IAsyncResult>();
 
    lock (working) // Bloqueo hasta que lanze todos los clientes
    {
        foreach (IImApplicationClient client in this.Clients)
        {
            working.Add(Test.BeginInvoke(client, Times, Interval,
                delegate(IAsyncResult IA)
                {
                    try
                    {
                        Test.EndInvoke(IA);
                        lock (working)
                        {
                            working.Remove(IA);         // Lo elimino de la lista,
                            if (working.Count == 0)     // y si era el último...
                                Monitor.Pulse(working); // envio pulso para liberar
                        }                               // la espera
                    }
                    catch (Exception ex)
                    {
                        IImApplicationClient asynClient =
                            IA.AsyncState as IImApplicationClient;
                        lock(errors)
                            errors.Add(new Exception
                                (client != null ? asynClient.Id : "Id unknown.", ex));
                    }
                }, client));
        }
 
        if (working.Count > 0) // Si se han lanzado clientes...
            Monitor.Wait(working); // bloqueo en espera.
    }
 
    return errors;
}

El planteamiento es el siguiente:

  • Se usa una lista para tener controladas las llamadas asíncronas.
  • Cada vez que se lanza una llamada asíncrona, el IAsyncResult resultante se añade a la lista.
  • Se bloquea la lista hasta que todas han sido lanzadas, y si se ha lanzado más de una, se ejecuta un Monitor.Wait para que se detenga la ejecución ahí hasta que se realize un Monitor.Pulse.
  • Cada vez que una llamada asíncrona termina, se elimina su IAsyncResult de la lista.
  • Si el IAsyncResult es el último que quedaba, se realiza un Monitor.Pulse para que la ejecución pueda seguir puesto que ya finalizaron todas las llamadas asíncronas.

Sugerencias, como siempre, bienvenidas 😀

Pooling de llamadas asincronas| vtortola.NET

Visual Basic .NET vs C# .NET: ¿Cual es mejor y por que?

Hoy Second Nug tiene el honor de presentar a dos ponentes de excepción, Guillermo Som (el Guille) y Marino Posadas (el Ave Fénix), en la que será una gran batalla donde dos voces con gran experiencia expondrán sus mejores bazas en un duelo sin igual: VB .NET vs C# .NET.
Sabremos por qué se decantaron por un lenguaje u otro y nos presentarán su evolución en las nuevas versiones del .NET Framework. Nos desvelaran secretos y trucos de sus defendidos y veremos si es cierto aquello de que lo que se puede hacer con uno, se puede realmente hacer con el otro.
Además los asistentes podrán resolver sus dudas preguntando a nuestros expertos y participar en el resultado final de la contienda.
El eterno dilema al descubierto. ¿Quién será el vencedor?

El evento será a las 19:30 – 21:30 (GMT+2), y como en las anteriores ocasiones, se retransmitirá vía Web a través de Live Meeting.

Si no tienes Live Meeting, puedes descargarlo en el siguiente enlace.

Podéis registraros en el evento en el siguiente enlace.