在Dispatcher线程上调用Dispatcher.Invoke()

时间:2014-09-19 11:38:07

标签: c# wpf com dispatcher

我在使用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应用程序调用的方法中(是的,我知道)。可能有什么影响?

1 个答案:

答案 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 }