正在取消在 Prism EventAggregator 上排队的其他 运行 个任务
Cancelling other running tasks queued on Prism EventAggregator
我有一个使用 Prism 的 WPF 应用程序。当用户从数据网格中选择行时,它会在 EventAggregator 上触发 SelectionUpdated 事件。
我的其他 ViewModel 中的一个正在侦听该事件,当它收到该事件时,将启动一个异步进程以根据选择检索一些远程结果。这最多可能需要 10 秒钟。当它取回结果时,它会使用结果更新 ViewModel,然后将结果绑定到结果网格。
我遇到的问题是,如果用户在第一次选择 运行 时进行第二次选择,即选择第 2-4 行,然后改变主意选择第 2-8 行,似乎 EventAggregator 是一个单线程管道和第一个接收到的事件必须在第二个开始之前完全完成,包括异步位。
我实际上想要一种在收到第二个请求时取消第一个请求的方法。我的视图代码隐藏是捕获选择事件的地方,然后此代码隐藏发布 SelectionUpdated 事件。因此,如果 EventAggregator 只是单线程,那么我需要在代码隐藏中以某种方式告诉我当前正在处理 SelectionUpdated 事件的视图模型取消并退出,释放 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 的最后一次调用,但我不知道该怎么做。
有什么想法吗?
默认情况下,您订阅发布者线程。您想要订阅线程池线程,以便您的订阅可以 运行 并行。
_eventAggregator.GetEvent<SelectionUpdatedEvent>().Subscribe(async x => await UpdateSelectedEntries(x), ThreadOption.BackgroundThread);
然后你的订阅者会取消之前任务使用的CancellationToken
,换成他自己的(这部分显然要同步)
我有一个使用 Prism 的 WPF 应用程序。当用户从数据网格中选择行时,它会在 EventAggregator 上触发 SelectionUpdated 事件。
我的其他 ViewModel 中的一个正在侦听该事件,当它收到该事件时,将启动一个异步进程以根据选择检索一些远程结果。这最多可能需要 10 秒钟。当它取回结果时,它会使用结果更新 ViewModel,然后将结果绑定到结果网格。
我遇到的问题是,如果用户在第一次选择 运行 时进行第二次选择,即选择第 2-4 行,然后改变主意选择第 2-8 行,似乎 EventAggregator 是一个单线程管道和第一个接收到的事件必须在第二个开始之前完全完成,包括异步位。
我实际上想要一种在收到第二个请求时取消第一个请求的方法。我的视图代码隐藏是捕获选择事件的地方,然后此代码隐藏发布 SelectionUpdated 事件。因此,如果 EventAggregator 只是单线程,那么我需要在代码隐藏中以某种方式告诉我当前正在处理 SelectionUpdated 事件的视图模型取消并退出,释放 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 的最后一次调用,但我不知道该怎么做。
有什么想法吗?
默认情况下,您订阅发布者线程。您想要订阅线程池线程,以便您的订阅可以 运行 并行。
_eventAggregator.GetEvent<SelectionUpdatedEvent>().Subscribe(async x => await UpdateSelectedEntries(x), ThreadOption.BackgroundThread);
然后你的订阅者会取消之前任务使用的CancellationToken
,换成他自己的(这部分显然要同步)