使用接收简化异步的Silverlight Web服务请求 [英] Using Rx to simplify an asynchronous Silverlight web service request

查看:161
本文介绍了使用接收简化异步的Silverlight Web服务请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用接收写了一个简单的Silverlight客户端库,我的WCF的Web服务,但是我发现有时候我缺少完成的事件。

I have written a simplified Silverlight client library for my WCF web service using Rx, however I notice sometimes I'm missing completed events.

public IObservable<XElement> GetReport(string reportName)
{
    return from client in Observable.Return(new WebServiceClient())
           from request in Observable.ToAsync<string>(client.GetReportDataAsync)(reportName)
           from result in Observable.FromEvent<GetReportDataCompletedEventArgs>(client, "GetReportDataCompleted").Take(1)
           from close in this.CloseClient(client)
           select result.EventArgs.Result;
}

相信问题是由以下事实web服务调用和之前订阅完成事件返回而引起的。我无法弄清楚如何让接收到之前订阅事件的异步调用。我想StartWith但要求输入和输出类型是相同的,任何想法?

I believe the issue is caused by the fact that the web service is called and returns prior to subscribing to the completed event. I can't figure out how to get Rx to subscribe to the event prior to the Async call. I tried StartWith but that requires that the input and output types be the same, any ideas?

推荐答案

似乎是最好的答案是使用Observable.CreateWithDisposable()

Seems like the best answer is to use Observable.CreateWithDisposable()

例如

public IObservable<XElement> GetReport(string reportName)
{
    return from client in Observable.Return(new WebServiceClient())
            from completed in Observable.CreateWithDisposable<GetReportDataCompletedEventArgs>(observer =>
                {
                    var subscription = Observable.FromEvent<GetReportDataCompletedEventArgs>(client, "GetReportDataCompleted")
                        .Take(1)
                        .Select(e => e.EventArgs)
                        .Subscribe(observer);
                    client.GetReportDataAsync(reportName);
                    return subscription;
                })
            from close in this.CloseClient(client)
            select completed.Result;
}

为了更方便与我重构了CreateWithDisposable到可以用我所有的Web服务调用,包括事件参数自动确定事件名称中使用的通用功能,工作类型:

To make this easier to work with I refactored the CreateWithDisposable into a common function that can be used with all my web service calls, including automatically determining the event name from the event args type:

private IObservable<T> CallService<T>(ICommunicationObject serviceClient, Action start) where T : AsyncCompletedEventArgs
{
    if (typeof(T) == typeof(AsyncCompletedEventArgs))
    {
        throw new InvalidOperationException("Event arguments type cannot be used to determine event name, use event name overload instead.");
    }

    string completedEventName = typeof(T).Name.TrimEnd("EventArgs");
    return CallService<T>(serviceClient, start, completedEventName);
}

private IObservable<T> CallService<T>(ICommunicationObject serviceClient, Action start, string completedEventName) where T : AsyncCompletedEventArgs
{
    return Observable.CreateWithDisposable<T>(observer =>
    {
        var subscription = Observable.FromEvent<T>(serviceClient, completedEventName).Take(1).Select(e => e.EventArgs).Subscribe(observer);
        start();
        return subscription;
    });
}

// Example usage:
public IObservable<XElement> GetReport(string reportName)
{
    return from client in Observable.Return(new WebServiceClient())
            from completed in this.CallService<GetReportDataCompletedEventArgs>(client, () => client.GetReportDataAsync(reportName))
            from close in this.CloseClient(client)
            select completed.Result;
}

/// <summary>
/// Asynchronously closes the web service client
/// </summary>
/// <param name="client">The web service client to be closed.</param>
/// <returns>Returns a cold observable sequence of a single success Unit.</returns>
private IObservable<AsyncCompletedEventArgs> CloseClient(WebServiceClient client)
{
    return this.CallService<AsyncCompletedEventArgs>(client, client.CloseAsync, "CloseCompleted");
}

希望这可以帮助其他人!

Hope this helps someone else!

这篇关于使用接收简化异步的Silverlight Web服务请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆