c# - 为什么 Prism DelegateCommands 有时会导致线程异常?

标签 c# wpf multithreading prism delegatecommand

下面的示例使用了 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/

相关文章:

c# - 自动更新版本号

Python3-Pyqt5如何通过异常或按退出按钮结束线程中的循环

java - 唯一值的对象锁定

c# - DateTime.TryParseExact 未按预期工作

c# - 自动倒计时调整数据库记录

c# - 使用 string[] args 从命令行调用控制台应用程序

c# - 获取按钮的每秒点击次数

c# - 子扩展器引发父扩展器的扩展和折叠事件?

c# - 我的快捷键不起作用

ios - 如何在后台渲染 CALayer