阻止多次执行ReactiveCommand(CreateAsyncTask)



是否可以防止多次执行ReactiveCommand。

这是我使用的"简单"代码:

创建命令:

this.LoadCommand = ReactiveCommand.CreateAsyncTask(
            async _ => await this._dataService.Load(),
            RxApp.TaskpoolScheduler);

在我将订阅添加到命令后:

this.LoadCommand.Subscribe(assets => ...);

最后,我执行命令:

this.LoadCommand.ExecuteAsyncTask();

如果我在多个位置多次调用ExecuteAsyncTask,我希望任何后续调用都等待第一个调用完成。

编辑:以下是Subscribe方法的完整代码:

    this.LoadCommand.Subscribe(assets =>
            {
                Application.Current.Dispatcher.Invoke(
                    DispatcherPriority.Background, 
                    new Action(() => this.Assets.Clear()));
                foreach (Asset asset in assets)
                {
                    Application.Current.Dispatcher.Invoke(
                        DispatcherPriority.Background, 
                        new Action<Asset>(a =>
                        {
                            this.Assets.Add(a);
                        }), asset);
                }
            });

谢谢,

阿德里安。

我下载了您的示例应用程序,并能够修复它

1) 我在您的命令创建中取出了Rx.TaskpoolScheduler参数。这告诉它使用该调度程序传递结果,我认为您应该坚持在UI线程上传递结果。

2) 由于通过进行此更改,您现在正在UI线程上运行Subscribe逻辑,因此不需要处理所有的Invoking。您可以直接访问收藏:

this.LoadCommand.Subscribe(dataCollection =>
                                      {
                                          DataCollection.Clear();
                                          DataCollection.AddRange(dataCollection);
                                      });

仅仅做了这两个改变就让它"工作"了。

我不是专家,但我认为实际发生的情况是,您拥有的实际ReactiveCommand"LoadCommand"立即返回并在各种TaskPool线程上传递结果。因此,它永远不会允许在命令本身中并发,这是经过设计的。然而,我认为订阅是同时发生的(竞争),因为每个订阅都来自不同的线程。所以所有的清除都发生了,然后所有的添加都发生了。

通过在同一个线程上订阅和处理所有内容,可以避免这种情况,如果可以在UI线程上管理它,则不需要调用Dispatcher。

此外,在这种特殊情况下,在优先级为DispatcherPriority.Background的Dispatcher上使用Invoke似乎以非串行方式执行事情,不确定确切的顺序,但它似乎以相反的顺序执行所有清除,然后添加(我增加了它们,这样我就可以判断是哪个调用)。因此,肯定有一些话要说。FWIW将优先级更改为DispatcherPriority.Send,使其保持串行并显示"预期"行为。话虽如此,如果可以的话,我仍然倾向于完全避免调用Dispatcher。

相关内容

  • 没有找到相关文章

最新更新