这是WPF(.NET Framework 4.8)。我需要在UI中提供两个<Button>
来启动和停止长时间运行的后台进程。启动按钮最初应该是启用的,并且在发出命令后将被禁用(以避免第二次单击)。停止按钮最初将被禁用,并且在进程开始运行后将被启用。
我使用Windows Community Toolkit's MVVM library中提供的AsyncRelayCommand
。按钮通过普通的XAML绑定绑定到它们的VM。底层命令如下所示:
private AsyncRelayCommand _StartPumpingCommand;
public AsyncRelayCommand StartPumpingCommand
{
get
{
_StartPumpingCommand ??= new AsyncRelayCommand(async (CancellationToken token) =>
{
dispatcher.Invoke(() => _CancelPumpingCommand.NotifyCanExecuteChanged());
await SomeTask(token);
},
() => {
/* SomeTask is not running and a cancellation has not been requested */
return !_StartPumpingCommand.IsRunning && !_StartPumpingCommand.IsCancellationRequested;
});
return _StartPumpingCommand;
}
}
private RelayCommand _CancelPumpingCommand;
public RelayCommand CancelPumpingCommand
{
get
{
_CancelPumpingCommand ??= new RelayCommand(() =>
{
if(_StartPumpingCommand?.IsRunning??false)
_StartPumpingCommand.Cancel();
},
() => _StartPumpingCommand?.IsRunning??false);
return _CancelPumpingCommand;
}
}
问题:
1.我对这两个命令的实现是否正确?
AsyncRelayCommand
内部是否包含CancellationTokenSource
magic,或者我是否需要自己在VM类中创建一个并在上面的两个命令中使用它?
1.如何将StartPumpingCommand
的完成通知给CancelPumpingCommand
,以便UI中的按钮相应地被启用/禁用?我们是否应该在SomeTask()
返回后调用CancelPumpingCommand.NotifyCanExecuteChanged()
?由于CancelPumpingCommand
使用StartPumpingCommand.IsRunning
属性来决定其可用性,并且StartPumpingCommand
仍将运行,它将如何表现,对吗?
1条答案
按热度按时间6ie5vjzr1#
下面是在Community Toolkit中执行异步命令的正确方法,以防它对某人有帮助:
这是完全正确的。我的UI是完全响应的(没有死锁),我可以取消和重新启动任务任意次数。这表明
AsyncRelayCommand
内部包含任务取消魔法,只需要等待方法就可以工作。