使用接收简化异步的Silverlight Web服务请求 [英] Using Rx to simplify an asynchronous Silverlight web service request
问题描述
我一直在使用接收写了一个简单的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屋!