Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么Prism DelegateCommand有时会导致线程异常?_C#_Wpf_Multithreading_Prism_Delegatecommand - Fatal编程技术网

C# 为什么Prism DelegateCommand有时会导致线程异常?

C# 为什么Prism DelegateCommand有时会导致线程异常?,c#,wpf,multithreading,prism,delegatecommand,C#,Wpf,Multithreading,Prism,Delegatecommand,下面的示例使用了Prism 6.1中的DelegateCommand,但我在5.0中产生了相同的问题 使用以下视图模型(省略视图,仅由2个按钮组成): 如果首先调用ActiveCommand,则会发生以下异常: WindowsBase.dll中发生“System.InvalidOperationException”类型的异常,但未在用户代码中处理 其他信息:调用线程无法访问此对象,因为其他线程拥有它 据我所知,这是标准的“如果您不在UI线程上,则不允许与Wpf控件对话”例外。这似乎与方法摘要不符

下面的示例使用了Prism 6.1中的DelegateCommand,但我在5.0中产生了相同的问题

使用以下视图模型(省略视图,仅由2个按钮组成):

如果首先调用ActiveCommand,则会发生以下异常:

WindowsBase.dll中发生“System.InvalidOperationException”类型的异常,但未在用户代码中处理

其他信息:调用线程无法访问此对象,因为其他线程拥有它

据我所知,这是标准的“如果您不在UI线程上,则不允许与Wpf控件对话”例外。这似乎与方法摘要不符:

在UI线程上引发Prism.Commands.DelegateCommandBase.CanExecuteChange,以便每个命令调用程序都可以重新查询以检查命令是否可以执行

此外,我过去从非UI线程调用此方法时没有遇到任何问题

更奇怪的是,如果首先发出TestCommand,那么ActionCommand就会开始正常工作。我已经检查了Task.Run块中的代码,并且在所有情况下都在非UI线程上运行

不幸的是,我不能在我的实际代码中使用它作为一种变通方法——我曾尝试在工作线程调用RaiseCanceTechChanged之前让UI线程调用RaiseCanceTechChanged,但它没有帮助


RaiseCanceTechChanged有什么理由这样做吗?任何修复或解决方法?

您正在UI线程上创建TestCommand,并尝试在单独的线程上访问它。你不能那样做。如果您想做的只是启动can-execute,那么只需等待任务。运行并调用它

    public MainWindowViewModel()
    {
        TestCommand = new DelegateCommand(Test, CanTest);

        ActionCommand = new DelegateCommand(async () => 
        {
            await Task.Run(() =>
            {
                Thread.Sleep(1000);
            });

            TestCommand.RaiseCanExecuteChanged();
        });
    }

我认为文件是错误的。我没有看到任何导致事件在UI线程上被调用的代码。作者知道,但是他的问题是,如果你将鼠标悬停在
RaiseCanceTechChanged
上,并查看与之相关的文档,它表明它将在UI线程上引发事件。已提交一个问题,XML注释将得到澄清:您在问题报告中的示例(以OP的代码为例)不是一个好的示例。您需要有人注册到CanExceute事件,如果从非UI线程引发,该事件将引发异常(op有一个带有两个按钮的视图,他没有包含填充此卷的代码)。委托本身并不关心它在哪个线程上被调用,引发跨线程异常的是OP绑定到它的视图。应该知道应该更新文档,以便更清楚地了解DelegateCommand没有做任何特殊的事情来在UI线程上引发任何事。出于了解的目的,这在Prism v2中通过使用Dispatcher得到了支持,但后来在v2.2及更高版本中被删除。这就是XML注释的来源。它们从未更新过。。。与大多数文档一样:)
    public MainWindowViewModel()
    {
        TestCommand = new DelegateCommand(Test, CanTest);

        ActionCommand = new DelegateCommand(async () => 
        {
            await Task.Run(() =>
            {
                Thread.Sleep(1000);
            });

            TestCommand.RaiseCanExecuteChanged();
        });
    }