【问题标题】:Managing async service calls using Silverlight and Reactive Extensions使用 Silverlight 和响应式扩展管理异步服务调用
【发布时间】:2011-07-21 13:19:42
【问题描述】:

所以我正在阅读 Rx 并且很难理解它。我有一个 Silverlight 应用程序,需要异步调用 6 次特定服务。在过去,我们会通过调用并查询 userState/token 以将响应与请求相匹配来处理这个问题,因为它们不能保证按照我们调用它们的顺序返回。然而,我怀疑 Rx 以一种更优雅的方式处理这个问题。但我无法让它工作。这是我到目前为止所拥有的......

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);
}

我希望你能在这里看到我想要实现的目标......

我最终得到的是所有 myObject 都被设置为返回的第一个调用的结果。

我确定这很愚蠢,但我还没有弄清楚。

谢谢:)

【问题讨论】:

    标签: silverlight system.reactive


    【解决方案1】:

    考虑尝试使用 Observable.FromAsyncPattern 而不是 Observable.FromEventPattern。在 Silverlight(和电话)中使用 FromAsyncPattern 有一个技巧,因为服务代理不会直接公开 BeginInvoke/EndInvoke 对。但是,如果您使用服务代理的接口而不是服务代理本身,则可以访问开始/结束模式:

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

    现在,您可以从使用 foreach(LINQ 的反模式)切换到将 myCollection 转换为 myCollection 和服务请求之间的 observable 和 SelectMany,如下所示:

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

    另外需要注意的是:如果您以这种方式在 silverlight 中使用 FromAsyncPattern,结果将在后台线程中返回。您需要小心将 teo 委托给调度员。

    如果您想看到这一点,请查看我在 http://channel9.msdn.com/events/MIX/MIX11/EXT08 的最后 20 分钟左右的 Mix 演示。

    【讨论】:

    • 谢谢!这很有效,而且启动起来看起来很棒:-)我想知道,要将结果编组回 UI 线程,我不能只将最后一行更改为 requestResult.ObserveOn(SynchronizationContext.Current).Subscribe(...) ?
    • 在 ObserveOn 上是的。或者,如果您添加对适当 System.Reactive.???.Threading 库的引用,您可以使用 requestResult.ObserveOnDispatcher().Subscribe(...)
    • 很好的答案 - 正如 Jim 使用查询语法间接展示的那样,发出请求的关键是使用 SelectMany
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 2011-07-20
    相关资源
    最近更新 更多