在Dispatcher线程上调用Dispatcher.Invoke()
本文关键字:Dispatcher Invoke 线程 调用 | 更新日期: 2023-09-27 18:22:28
我在使用window显示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线程,那么调用dispatcher.Invoke应该相当于直接调用该方法。显然这是错误的,但有人能解释为什么吗?
使问题复杂化的是,这段代码在一个方法中,该方法是从VB6应用程序通过COM调用的(是的,我知道)。这会产生什么影响?
我怀疑这里的问题是第一种情况下错误的.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 }
。