取消在Prism EventAggregator

时间:2018-05-16 15:46:27

标签: c# wpf mvvm prism eventaggregator

我有一个使用Prism的WPF应用程序。当用户从数据网格中选择行时,它会在EventAggregator上触发SelectionUpdated事件。

我的其他一个ViewModel正在监听该事件,当它收到它时,启动异步过程以根据选择检索一些远程结果。这可能需要10秒钟。当它返回结果时,它会使用结果更新ViewModel,然后将结果绑定到结果网格。

我遇到的问题是,如果用户在第一次选择时进行第二次选择,即选择第2-4行然后改变主意并选择第2-8行,则看起来EventAggregator是单线程管道而第一个收到的事件必须在第二个开始之前完全完成,包括异步位。

如果收到第二个请求,我实际上想要一种取消第一个请求的方法。我对视图的代码隐藏是捕获选择事件的地方,然后这个代码隐藏发布SelectionUpdated事件。因此,如果EventAggregator只是单线程,那么我需要在代码隐藏中使用某种方式告诉我当前处理SelectionUpdated事件的viewmodel,取消并退出,释放EventAggregator subcribe()管道以处理第二个事件立即

希望这是有道理的。我的代码背后。

Grid.MouseLeftButtonUp += (sender, args) =>
{
    var selectedEntries = Grid.SelectedCells.Select(c => c.Item as EntryViewModel).Where(c => c != null).Distinct().ToArray();
    _eventAggregator.GetEvent<SelectionUpdatedEvent>().Publish(selectedEntries);
};

收听ViewModel(仅限相关行)

_eventAggregator.GetEvent<SelectionUpdatedEvent>().Subscribe(async x => await UpdateSelectedEntries(x));

private async Task UpdateSelectedEntries(EntryViewModel[] selectedEntries)
{
    _selectedEntries = selectedEntries;
    RaisePropertyChanged(nameof(SelectedText));
    RaisePropertyChanged(nameof(SelectedBreakdown));

    await RecalculateAll();
}

private async Task RecalculateAll()
{
    try
    {
        var entryIds = _selectedEntries.SelectMany(s => s.StatusInfo.ValidEntryIds).OrderBy(t => t).ToArray();
        ProcessingCount++;
        var results = await _resultsService.GetResults(_resultType, entryIds);
...
}

对于GetResults的最后一次调用,如果我的代码隐藏已经检测到新的选择,我想要中断,但我无法弄清楚如何执行此操作。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

默认情况下,您订阅发布商线程。您希望订阅线程池线程,以便您的订阅可以并行运行。

_eventAggregator.GetEvent<SelectionUpdatedEvent>().Subscribe(async x => await UpdateSelectedEntries(x), ThreadOption.BackgroundThread);

然后,您的订阅者将取消上一个任务使用的CancellationToken,将其替换为自己的(此部分显然必须同步)。