下面的示例使用 Prism 6.1 中的 DelegateCommand,但我在 5.0 中产生了相同的问题。
使用以下视图模型(视图省略,仅包含 2 个按钮):
public class MainWindowViewModel
{
public DelegateCommand TestCommand { get; set; }
public DelegateCommand ActionCommand { get; set; }
public MainWindowViewModel()
{
TestCommand = new DelegateCommand(()=> TestCommand.RaiseCanExecuteChanged());
ActionCommand = new DelegateCommand(() =>
{
Task.Run(() =>
{
Thread.Sleep(1000);
TestCommand.RaiseCanExecuteChanged();
});
});
}
}
如果先调用 ActiveCommand,则会发生此异常:
WindowsBase.dll 中出现“System.InvalidOperationException”类型的异常,但未在用户代码中处理
附加信息:调用线程无法访问此对象,因为不同的线程拥有它。
据我所知,这是标准的“如果您不在 UI 线程上,则不允许您与 Wpf 控件交谈”例外。这似乎与方法摘要不一致:
在 UI 线程上引发 Prism.Commands.DelegateCommandBase.CanExecuteChanged,以便每个命令调用者都可以重新查询以检查命令是否可以执行。
此外,我过去从非 UI 线程调用此方法也没有问题。
更奇怪的是,如果首先引发 TestCommand,那么 ActionCommand 开始正常工作。我已经检查过了,Task.Run 块中的代码在所有情况下都在非 UI 线程上运行。
不幸的是,我不能在我的真实代码中使用它作为解决方法——我尝试在工作线程执行之前让 UI 线程调用 RaiseCanExecuteChanged,但它没有帮助。
RaiseCanExecuteChanged 有什么理由这样做吗?任何修复或解决方法?