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

发布于 2024-10-13 01:46:48 字数 1524 浏览 5 评论 0原文

我有以下代码来设置我的 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”子句,代码可以工作,但如果我将其放入,则查询永远不会完成。

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

干杯, -蒂姆

I have the following bit of code to set up my Rx hookups:

Event related definitions:

    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;

Initialization:

            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" is the WCF client and everything else is fairly self-explanatory.

The "TakeUntil" is there to stop the user stomping on himself when doing a new query while in the middle of a currently running one. However, while the code works if I remove the "TakeUntil" clause, if I put it in, the query is never completed.

Is this the correct pattern? If so, am I doing something wrong?

Cheers,
-Tim

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

待"谢繁草 2024-10-20 01:46:48

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

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

TakeUntil terminates the subscription when a value is received from its argument, so your first queryObservable starts up the query but also terminates the subscription to the complete events.

The simpler solution is to setup an IObservable around your actual query, and then use Switch to ensure that only one query runs at a time.

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

Then you can do this:

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

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

This sets up one continuous flow, whereby each "Query" event starts a query which emits the complete event from that query. New queries automatically teriminate the previous query (if possible) and start a new one.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文