gpt4 book ai didi

silverlight - 使用 Rx 简化异步 Silverlight Web 服务请求

转载 作者:行者123 更新时间:2023-12-04 02:37:57 27 4
gpt4 key购买 nike

我已经使用 Rx 为我的 WCF Web 服务编写了一个简化的 Silverlight 客户端库,但是我注意到有时我会丢失已完成的事件。

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 服务这一事实造成的。我不知道如何让 Rx 在异步调用之前订阅事件。我试过 StartWith 但这要求输入和输出类型相同,有什么想法吗?

最佳答案

似乎最好的答案是使用 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 服务调用,包括从事件参数类型自动确定事件名称:
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");
}

希望这对其他人有帮助!

关于silverlight - 使用 Rx 简化异步 Silverlight Web 服务请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3801505/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com