我在使用Window.Show:
显示WPF窗口时遇到问题System.InvalidOperationException未处理 消息:WindowsBase.dll中出现未处理的“System.InvalidOperationException”类型的异常 附加信息:调用线程无法访问此对象,因为其他线程拥有它。
足够公平 - 解决此问题的标准方法是使用Dispatcher.Invoke确保该窗口显示在Dispatcher线程上。
奇怪的是,就我所知,代码已经在Dispatcher线程上运行。
此代码触发异常:
if (Dispatcher.CurrentDispatcher.Thread != Thread.CurrentThread ||
Application.Current.Dispatcher.Thread != Thread.CurrentThread)
{
throw new ApplicationException("Current thread is not Dispatcher");
}
window.Show(); // throws InvalidOperationException
此代码可以正常工作:
if (Dispatcher.CurrentDispatcher.Thread != Thread.CurrentThread ||
Application.Current.Dispatcher.Thread != Thread.CurrentThread)
{
throw new ApplicationException("Current thread is not Dispatcher");
}
Dispatcher.CurrentDispatcher.Invoke(window.Show);
据我了解,如果当前线程是调度程序线程,则调用Dispatcher.Invoke应该等效于直接调用该方法。显然这是错误的,但有人可以解释为什么吗?
为了使问题复杂化,此代码位于通过COM从VB6应用程序调用的方法中(是的,我知道)。可能有什么影响?
答案 0 :(得分:2)
我怀疑这里的问题是第一种情况下错误的.NET同步上下文(或缺少它)。
据我所知,此代码是从非托管主机调用的,该主机自然没有在主UI线程上安装.NET同步上下文。
在第一种情况下尝试这个:
System.Diagnostics.Debug.WriteLine(new { System.Threading.SynchronizationContext.Current });
window.Show(); // throws InvalidOperationException
我希望您在调试输出中看到{ Current = null }
。
对于第二种情况,请执行以下操作:
Dispatcher.CurrentDispatcher.Invoke(() => {
System.Diagnostics.Debug.WriteLine(new { System.Threading.SynchronizationContext.Current });
window.Show();
});
这应输出{ Current = System.Windows.Threading.DispatcherSynchronizationContext }
。