我们正在为我们的catel 4.4.0 MVVM应用程序添加第二个UI线程。
我在第二个UI线程上创建了我的视图和视图模型,并使用DispatcherTimer定期更新视图模型。这部分似乎工作正常。但是,当我在视图模型的构造函数中创建Catel.MVVM.Command时,我遇到了问题。当命令的CanExecute触发时,我在第二个UI线程上收到System.InvalidOperationException。
这个命令没什么特别的。
private bool ImageClickCanExecute()
{
return true;
}
public void ImageClickAction()
{
if(ImageClickTarget != null)
Process.Start(ImageClickTarget.ToString());
}
视图也不是。
<Grid>
<Button Command="{Binding ImageClickCommand}">
<Image Name="ImageSource" Source="{Binding ImageSource, FallbackValue={x:Null}}"/>
</Button>
</Grid>
堆栈跟踪在下面。
0:010> !PrintException /d 00000282cb8effd0
Exception object: 00000282cb8effd0
Exception type: System.Reflection.TargetInvocationException
Message: Exception has been thrown by the target of an invocation.
InnerException: System.InvalidOperationException, Use !PrintException 00000282cb8edee8 to see more.
StackTrace (generated):
SP IP Function
000000B0459FD510 0000000000000000 mscorlib_ni!System.RuntimeMethodHandle.InvokeMethod(System.Object, System.Object[], System.Signature, Boolean)+0x1
000000B0459FD510 00007FFFCC5E1C20 mscorlib_ni!System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(System.Object, System.Object[], System.Object[])+0x80
000000B0459FD580 00007FFFCC5BE789 mscorlib_ni!System.Delegate.DynamicInvokeImpl(System.Object[])+0x99
000000B0459FD5D0 00007FFF70FC83AE UNKNOWN!Catel.EventHandlerExtensions.SplitInvoke(System.Delegate, System.Object[])+0xfe
000000B0459FD630 00007FFF7164E085 UNKNOWN!Catel.EventHandlerExtensions.SafeInvoke(System.EventHandler, System.Object, System.EventArgs)+0x55
000000B0459FD680 00007FFF71674998 UNKNOWN!Catel.MVVM.Command`2+<<RaiseCanExecuteChanged>b__32_0>d[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].MoveNext()+0x38
000000B0459FD7B0 00007FFFCD2E1224 mscorlib_ni!System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)+0xd3f9c4
000000B0459FD7F0 00007FFFCC5A17AD mscorlib_ni!System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)+0x3d
000000B0459FD820 00007FFF71674515 UNKNOWN!Catel.MVVM.Command`2+<>c__DisplayClass35_0+<<AutoDispatchIfRequiredAsync>b__0>d[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].MoveNext()+0xf5
000000B0459FD9B0 00007FFFCCFCDA88 mscorlib_ni!System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__6_0(System.Object)+0x38
000000B0459FD9E0 00007FFFA8119C0E WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)+0xae
000000B0459FDA50 00007FFFA8119AC6 WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)+0x36
000000B0459FDAA0 00007FFFA811CA2B WindowsBase_ni!System.Windows.Threading.DispatcherOperation.InvokeImpl()+0x10b
000000B0459FDB20 00007FFFCC5CA79E mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x15e
000000B0459FDBF0 00007FFFCC5CA637 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x17
000000B0459FDC20 00007FFFCC5CA5F2 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x52
000000B0459FDC70 00007FFFA8333810 WindowsBase_ni!MS.Internal.CulturePreservingExecutionContext.Run(MS.Internal.CulturePreservingExecutionContext, System.Threading.ContextCallback, System.Object)+0x80
000000B0459FDCD0 00007FFFA811C784 WindowsBase_ni!System.Windows.Threading.DispatcherOperation.Invoke()+0x64
000000B0459FDD30 00007FFFA8117C24 WindowsBase_ni!System.Windows.Threading.Dispatcher.ProcessQueue()+0x1a4
000000B0459FDDB0 00007FFFA8118061 WindowsBase_ni!System.Windows.Threading.Dispatcher.WndProcHook(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)+0x71
000000B0459FDE30 00007FFFA8119E53 WindowsBase_ni!MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)+0xc3
000000B0459FDEC0 00007FFFA8119D82 WindowsBase_ni!MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)+0x82
000000B0459FDF10 00007FFFA8119BC9 WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)+0x69
000000B0459FDF80 00007FFFA8119AC6 WindowsBase_ni!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)+0x36
000000B0459FDFD0 00007FFFA8117583 WindowsBase_ni!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)+0x173
000000B0459FE070 00007FFFA81194FF WindowsBase_ni!MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)+0x11f
000000B0459FE390 0000000000000000 WindowsBase_ni!MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)+0x1
000000B0459FE450 00007FFFA812D8FC WindowsBase_ni!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)+0xec
000000B0459FE4E0 00007FFFA26A98B3 PresentationFramework_ni!System.Windows.Application.RunDispatcher(System.Object)+0x73
000000B0459FE520 00007FFFA26A969D PresentationFramework_ni!System.Windows.Application.RunInternal(System.Windows.Window)+0x8d
000000B0459FE580 00007FFF70FD70F7 UNKNOWN!xxx.Wpf.App.Main()+0x67
000000B0459FF0C0 0000000000000000 mscorlib_ni!System.AppDomain._nExecuteAssembly(System.Reflection.RuntimeAssembly, System.String[])+0x1
000000B0459FF0C0 00007FFFCCD57EBF mscorlib_ni!System.AppDomain.ExecuteAssembly(System.String, System.Security.Policy.Evidence, System.String[])+0x7f
000000B0459FF110 00007FFF7053434E UNKNOWN!Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()+0x3e
000000B0459FF150 00007FFFCC5CA79E mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x15e
000000B0459FF220 00007FFFCC5CA637 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x17
000000B0459FF250 00007FFFCC5CA5F2 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x52
000000B0459FF2A0 00007FFFCC51BEF2 mscorlib_ni!System.Threading.ThreadHelper.ThreadStart()+0x52
StackTraceString: <none>
HResult: 80131604
0:010> !PrintException /d 00000282cb8edee8
Exception object: 00000282cb8edee8
Exception type: System.InvalidOperationException
Message: The calling thread cannot access this object because a different thread owns it.
InnerException: <none>
StackTrace (generated):
SP IP Function
000000B0459FCD70 00007FFFA8446977 WindowsBase_ni!System.Windows.Threading.Dispatcher.VerifyAccess()+0x32faf7
000000B0459FCDA0 00007FFFA8112806 WindowsBase_ni!System.Windows.DependencyObject.GetValue(System.Windows.DependencyProperty)+0x26
000000B0459FCE00 00007FFFA27EBB5B PresentationFramework_ni!System.Windows.Controls.Primitives.ButtonBase.get_Command()+0x2b
000000B0459FCE30 00007FFFA27EBB00 PresentationFramework_ni!System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute()+0x10
StackTraceString: <none>
HResult: 80131509
答案 0 :(得分:0)
这是因为,默认情况下,命令会使用DispatcherService
自动分派更改通知。由于您正在运行边缘情况(2 ui线程),我建议您关闭自动调度并自己处理。
由于这是一个静态受保护的成员,您需要从CommandBase
派生自己的命令类,并将AutomaticallyDispatchEvents
设置为false
。
PS。我建议使用IProcessService
而不是直接使用Process.Start
,它允许您模拟它或在需要时替换它。