2011-07-21 15 views
5

Así que estoy leyendo en Rx y teniendo dificultades para asimilarlo. Tengo una aplicación de Silverlight que necesita hacer 6 llamadas a un servicio específico de forma asincrónica. En los viejos tiempos, manejamos esto al hacer las llamadas y consultar el userState/token para que coincida con la respuesta a la solicitud, ya que no se garantiza que vuelvan en el orden en que los llamamos. Sin embargo, sospecho que Rx maneja esto de una manera mucho más elegante. Pero no puedo hacer que funcione. Esto es lo que tengo hasta ahora ...Administración de llamadas de servicio asíncrono usando Silverlight y las extensiones reactivas

myCollection.Add(new myObject(1)); 
myCollection.Add(new myObject(2)); 
myCollection.Add(new myObject(3)); 
myCollection.Add(new myObject(4)); 
myCollection.Add(new myObject(5)); 
myCollection.Add(new myObject(6)); 

foreach (var myItem in myCollection) 
{ 
    var myObservable = Observable.FromEventPattern<MyServiceMethodCompletedEventArgs> 
    (
     f => myServiceClient.MyServiceMethodCompleted += f, 
     f => myServiceClient.MyServiceMethodCompleted -= f 
    ).Take(1).ObserveOn(SynchronizationContext.Current); 

    myObservable.Subscribe 
    (
    s => 
    { 
     if (s.EventArgs.Error == null) 
     { 

     myItem.MyProperty = s.EventArgs.Result; 
     } 
    } 
    ); 

    myServiceClient.MyServiceMethodAsync(myItem); 
} 

espero que puedan ver lo que estoy tratando de lograr aquí ...

Lo que es terminar con todo el ser myObject 's establecer el resultado de la primera llamada que devuelve.

Estoy seguro de que es algo tonto pero no he podido descifrarlo todavía.

Gracias :)

Respuesta

4

considerar tratar el Observable.FromAsyncPattern en lugar de Observable.FromEventPattern. Existe un truco para usar FromAsyncPattern en Silverlight (y en el teléfono) porque el proxy de servicio no expone directamente el par BeginInvoke/EndInvoke. Sin embargo, si se utiliza la interfaz para el proxy de servicio en lugar del propio proxy de servicio, se puede acceder al patrón de comenzar/final:

IMyService svc = new myServiceClient(); 
var svcObservable = Observable.FromAsyncPattern<T, MyServiceResultArgs> 
         (svc.BeginMyServiceMethod, svc.EndMyServiceMethod); 

Ahora, usted puede pasar de utilizar foreach (un anti-patrón con LINQ) a hacer su myCollection en un observable y SelectMany entre el myCollection y la solicitud de servicio de la siguiente manera:

var requestResult = from myItem in myCollection.ToObservable() 
        from result in svcObservable(myItem) 
        select new {myItem, result}; 

requestResult.Subscribe(result => result.myItem.myProperty = result.result); 

una palabra adicional de precaución: Si se utiliza el FromAsyncPattern en Silverlight esta manera, el resultado va a volver sobre un fondo hilo. Tendrá que ocuparse de delegarle a su operador.

Si desea ver esto en acción, eche un vistazo a los últimos 20 minutos más o menos de mi presentación Mix al http://channel9.msdn.com/events/MIX/MIX11/EXT08.

+0

¡Gracias! Esto funciona y se ve muy bien para arrancar :-) Me pregunto, para ordenar los resultados de nuevo a la secuencia de comandos UI, ¿no puedo simplemente cambiar la última línea para requestResult.ObserveOn (SynchronizationContext.Current) .Subscribe (...) ? – Senkwe

+0

Sí en el ObserveOn. Alternativamente, si agrega una referencia a la biblioteca apropiada System.Reactive.???.Threading, puede usar requestResult.ObserveOnDispatcher(). Subscribe (...) –

+0

Gran respuesta: como Jim muestra indirectamente el uso de la sintaxis de la consulta, la clave para emitir las solicitudes está utilizando SelectMany –

Cuestiones relacionadas