相关疑难解决方法(0)

Prism 5 DelegateCommandBase.RaiseCanExecuteChanged抛出InvalidOperationException

我刚刚从Prism 4.1更新到5,过去工作正常的代码现在抛出InvalidOperationExceptions.我怀疑根本原因是更新的异步DelegateCommands没有正确地编组到UI线程.

我需要能够从任何线程调用command.RaiseCanExecuteChanged()并为此在UI线程上引发CanExecuteChanged事件.Prism文档说这就是RaiseCanExecuteChanged()方法应该做的事情.然而,随着Prism 5的更新,它不再有效.CanExecuteChanged事件在非UI线程上调用,我获得下游InvalidOperationExceptions,因为在这个非UI线程上访问UI元素.

这是Prism文档,它提供了一个解决方案的提示:

DelegateCommand包括对异步处理程序的支持,并已移至Prism.Mvvm可移植类库.DelegateCommand和CompositeCommand都使用WeakEventHandlerManager来引发CanExecuteChanged事件.必须首先在UI线程上构造WeakEventHandlerManager,以正确获取对UI线程的SynchronizationContext的引用.

但是,WeakEventHandlerManager是静态的,所以我无法构造它...

根据Prism文档,有谁知道如何在UI线程上构建WeakEventHandlerManager?

这是一个失败的单元测试,可以重现问题:

    [TestMethod]
    public async Task Fails()
    {
        bool canExecute = false;
        var command = new DelegateCommand(() => Console.WriteLine(@"Execute"),
                                          () =>
                                          {
                                              Console.WriteLine(@"CanExecute");
                                              return canExecute;
                                          });
        var button = new Button();
        button.Command = command;

        Assert.IsFalse(button.IsEnabled);

        canExecute = true;

        // Calling RaiseCanExecuteChanged from a threadpool thread kills the test
        // command.RaiseCanExecuteChanged(); works fine...
        await Task.Run(() => command.RaiseCanExecuteChanged());

        Assert.IsTrue(button.IsEnabled);
    }
Run Code Online (Sandbox Code Playgroud)

这是异常堆栈:

测试方法Calypso.Pharos.Commands.Test.PatientSessionCommandsTests.Fails引发异常:System.InvalidOperationException:调用线程无法访问此对象,因为另一个线程拥有它.在System.Windows.Threading.Dispatcher.VerifyAccess()在System.Windows.DependencyObject.GetValue(的DependencyProperty DP)在System.Windows.Controls.Primitives.ButtonBase.get_Command()在System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute ()在System.Windows.Controls.Primitives.ButtonBase.OnCanExecuteChanged(对象发件人,EventArgs e)上System.Windows.Input.CanExecuteChangedEventManager.HandlerSink.OnCanExecuteChanged(对象发件人,EventArgs e)上Microsoft.Practices.Prism.Commands.WeakEventHandlerManager .CallHandler(对象发件人,事件处理程序事件处理程序)在Microsoft.Practices.Prism.Commands.WeakEventHandlerManager.CallWeakReferenceHandlers(对象发件人,List`1处理程序)在Microsoft.Practices.Prism.Commands.DelegateCommandBase.OnCanExecuteChanged()在Microsoft.Practices.Prism .Commands.DelegateCommandBase.RaiseCanExecuteChanged()在Calypso.Pharos.Commands.Test.PatientSessionCommandsTests <> c__DisplayClass10.b__e()中PatientSessionCommandsTests.cs:线71在SYSTE m.Threading.Tasks.Task.InnerInvoke()在System.Threading.Tasks.Task.Execute()---从先前位置栈跟踪其中抛出异常---在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess完(任务任务)位于Patient.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)的System.Runtime.CompilerServices.TaskAwaiter.GetResult(),位于PatientSessionCommandsTests.cs中的Calypso.Pharos.Commands.Test.PatientSessionCommandsTests.d__12.MoveNext() :行71 ---从先前的位置堆栈跟踪其中的例外是在系统抛出---在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(工作任务)在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(工作任务)结束.Runtime.CompilerServices.TaskAwaiter.GetResult()

c# prism prism-5

5
推荐指数
2
解决办法
1348
查看次数

标签 统计

c# ×1

prism ×1

prism-5 ×1