下面的示例使用了 Prism 6.1 中的 DelegateCommand,但我在 5.0 中产生了同样的问题。
使用以下 View 模型(省略 View ,仅包含 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,则会发生此异常:
An exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll but was not handled in user code
Additional information: The calling thread cannot access this object because a different thread owns it.
据我所知,这是标准的“如果您不在 UI 线程上,则不允许与 Wpf 控件对话”异常。这似乎与方法摘要不一致:
Raises Prism.Commands.DelegateCommandBase.CanExecuteChanged on the UI thread so every command invoker can requery to check if the command can execute.
此外,我过去从非 UI 线程调用此方法也没有问题。
更奇怪的是,如果首先引发 TestCommand,那么 ActionCommand 就会开始正常工作。我已经检查过,Task.Run block 中的代码在所有情况下都在非 UI 线程上运行。
不幸的是,我不能在我的真实代码中使用它作为解决方法 - 我已经尝试让 UI 线程在工作线程调用 RaiseCanExecuteChanged 之前调用它,但它没有帮助。
RaiseCanExecuteChanged 这样做有什么理由吗?任何修复或解决方法?
最佳答案
您正在 UI 线程上创建 TestCommand 并尝试在单独的线程上访问它。你不能那样做。如果您只想引发 can execute,那么只需 await Task.Run 然后调用它即可。
public MainWindowViewModel()
{
TestCommand = new DelegateCommand(Test, CanTest);
ActionCommand = new DelegateCommand(async () =>
{
await Task.Run(() =>
{
Thread.Sleep(1000);
});
TestCommand.RaiseCanExecuteChanged();
});
}
关于c# - 为什么 Prism DelegateCommands 有时会导致线程异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33660381/