时间:2011-01-19 22:48:58

标签: 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);
                }
            );

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

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

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

干杯, -Tim

1 个答案:

答案 0 :(得分:3)

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

这将设置一个连续流,每个“Query”事件启动一个查询,该查询从该查询中发出完整事件。新查询会自动删除先前的查询(如果可能)并开始新的查询。