是否可以防止多次执行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);
}
});
谢谢,
阿德里安。
答案 0 :(得分:1)
我下载了您的示例应用程序,并且能够修复它。这是我的2美分:
1)我在命令创建中取出了Rx.TaskpoolScheduler
参数。这告诉它使用该调度程序提供结果,我认为您希望坚持在UI线程上提供结果。
2)由于通过进行此更改,您现在正在UI线程上运行订阅逻辑,因此您无需处理所有调用。您可以直接访问该集合:
this.LoadCommand.Subscribe(dataCollection =>
{
DataCollection.Clear();
DataCollection.AddRange(dataCollection);
});
只进行这两项更改就会使其“正常工作”。
我不是专家,但我认为发生的事实是你所拥有的实际ReactiveCommand“LoadCommand”会立即返回并在各种TaskPool线程上提供结果。所以它永远不会允许Command本身内的并发,这是设计的。然而,我认为订阅,因为每个人都在一个不同的线程进入,同时发生(比赛)。所以所有的清除都发生了,然后是所有的补充。
通过在同一个线程上订阅和处理所有内容,您可以避免这种情况,如果您可以在UI线程上进行管理,则无需涉及调用Dispatcher。
此外,在这种特殊情况下,使用调度程序上的Invoke优先级DispatcherPriority.Background
似乎以非串行方式执行,不确定顺序,但它似乎完成所有清除,然后以相反的顺序添加(我递增它们以便我可以告诉它是哪个调用)。所以肯定有一些东西可以说。 FWIW将优先级更改为DispatcherPriority.Send
使其保持连续并显示“预期”行为。话虽如此,如果可以的话,我仍然希望完全避免调用Dispatcher。