silverlight - 在 Silverlight 中使用 Rx 进行 WCF 调用不适用于 TakeUntil

标签 silverlight wcf system.reactive

我有以下代码来设置我的 Rx 连接:

事件相关定义:

    public class QueryEventArgs : EventArgs
    {
        public SomeParametersType SomeParameters
        {
            get;
            set;
        }

        public object QueryContext
        {
                     get;
            set;
        }
    };

    public delegate void QueryDelegate(object sender, QueryEventArgs e);

    public event QueryDelegate QueryEvent;

初始化:

            queryObservable = Observable.FromEvent<QueryEventArgs>(this, "QueryEvent");
            queryObservable.Subscribe((e) =>
            {
                tbQueryProgress.Text = "Querying... ";
                client.QueryAsync(e.EventArgs.SomeParameters, e.EventArgs.QueryContext);
            });

            queryCompletedObservable = from e in Observable.FromEvent<QueryCompletedEventArgs>(client, "QueryCompleted").TakeUntil(queryObservable) select e;

            queryCompletedObservable.Subscribe((e) =>
                {
                    tbQueryProgress.Text = "Ready";
                    SilverlightClientService_QueryCompleted(e.Sender, e.EventArgs);
                },
                (Exception ex) =>
                {
                    SetError("Query error: " + ex);
                }
            );

“客户端”是 WCF 客户端,其他一切都是不言自明的。

“TakeUntil”用于阻止用户在当前正在运行的查询中间进行新查询时踩踏自己。但是,虽然如果我删除“TakeUntil”子句代码可以正常工作,但如果我将其放入,查询将永远不会完成。

这是正确的模式吗?如果是这样,我做错了什么吗?

干杯, -蒂姆

最佳答案

TakeUntil 在从其参数接收到值时终止订阅,因此您的第一个 queryObservable 启动查询但也终止对完整事件的订阅。

更简单的解决方案是围绕您的实际查询设置一个 IObservable,然后使用 Switch 确保一次只运行一个查询。

public static class ClientExtensions
{
    public static IObservable<QueryCompletedEventArgs> QueryObservable(
        this QueryClient client,
        object[] someParameters, object queryContext)
    {
       return Observable.CreateWithDisposable<QueryCompletedEventArgs>(observer =>
       {
            var subscription = Observable.FromEvent<QueryCompletedEventArgs>(
                    h => client.QueryCompleted += h,
                    h => client.QueryCompleted -= h
                )
                .Subscribe(observer);

            client.QueryAsync(someParameters, queryContext);

            return new CompositeDisposable(
                subscription,
                Disposable.Create(() => client.Abort())
            );
        });
    }
}

然后你可以这样做:

queryObservable = Observable.FromEvent<QueryEventArgs>(this, "QueryEvent");

queryObservable
    .Select(query => client.QueryObservable(
        query.EventArgs.SomeParameters, 
        query.EventArgs.QueryContext
    ))
    .Switch()
    .Subscribe(queryComplete =>
    {
        tbQueryProgress.Text = "Ready";
        // ... etc
    });

这建立了一个连续的流程,每个“查询”事件都会启动一个查询,该查询会从该查询中发出完整的事件。新查询会自动终止先前的查询(如果可能)并开始新的查询。

关于silverlight - 在 Silverlight 中使用 Rx 进行 WCF 调用不适用于 TakeUntil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4741711/

相关文章:

c# - silverlight 中的自定义复选框

silverlight - 确定在文本框中按下 Enter 键

asp.net - Uri.OriginalString 在 IIS 8.5 中编码

c# - 哪个响应式扩展代码更高效?

c# - 使用 RX 创建 IO 绑定(bind)可观察对象

c# - WCF HttpTransport : streamed vs buffered TransferMode

c# - 当目标是 ImageBrush.ImageSource 时,TemplateBinding 失败

不发送 StackTrace 的 WCF FaultException

wcf - 我需要将哪些 WCF 客户端文件 checkin SVN

c# - 了解从非阻塞 block 调用阻塞代码时的控制流?