2012-05-31 19 views
6

Estoy usando una biblioteca que realiza llamadas asíncronas y cuando se devuelve la respuesta se llama a un método de devolución de llamada con el resultado. Este es un patrón simple a seguir, pero ahora estoy golpeando un obstáculo. ¿Cómo hago múltiples llamadas a métodos asíncronos y espero (sin bloquear) para ellos? Cuando obtuve los datos de todo el servicio, me gustaría llamar a mi propio método de devolución de llamada que obtendrá los dos (o más) valores devueltos por el método asincrónico.Esperar múltiples devoluciones de llamada

¿Cuál es el patrón correcto a seguir aquí? Por cierto, no puedo cambiar la biblioteca para usar TPL o algo más ... Tengo que vivir con eso.

public static void GetDataAsync(Action<int, int> callback) 
{ 
    Service.Instance.GetData(r1 => 
    { 
     Debug.Assert(r1.Success); 
    }); 

    Service.Instance.GetData2(r2 => 
    { 
     Debug.Assert(r2.Success); 
    }); 

    // How do I call the action "callback" without blocking when the two methods have finished to execute? 
    // callback(r1.Data, r2.Data); 
} 

Respuesta

6

Lo que quiere es algo así como CountdownEvent. Prueba esto (suponiendo que se encuentre en .NET 4.0):

public static void GetDataAsync(Action<int, int> callback) 
{ 
    // Two here because we are going to wait for 2 events- adjust accordingly 
    var latch = new CountdownEvent(2); 

    Object r1Data, r2Data;  

    Service.Instance.GetData(r1 => 
    { 
     Debug.Assert(r1.Success); 
     r1Data = r1.Data; 
     latch.Signal(); 
    }); 

    Service.Instance.GetData2(r2 => 
    { 
     Debug.Assert(r2.Success); 
     r2Data = r2.Data; 
     latch.Signal(); 
    }); 

    // How do I call the action "callback" without blocking when the two methods have finished to execute? 
    // callback(r1.Data, r2.Data); 

    ThreadPool.QueueUserWorkItem(() => { 
     // This will execute on a threadpool thread, so the 
     // original caller is not blocked while the other async's run 

     latch.Wait(); 
     callback(r1Data, r2Data); 
     // Do whatever here- the async's have now completed. 
    }); 
} 
2

usted podría utilizar Interlocked.Increment para cada llamada que realice asíncrono. Cuando finalice, llame al Interlocked.Decrement y compruebe si hay cero, si es cero, llame a su propia devolución de llamada. Tendrá que almacenar r1 y r2 fuera de los delegados de devolución de llamada.

Cuestiones relacionadas