2014-09-19 83 views
3

我具有顯示使用Window.Show WPF窗口的問題調用Dispatcher.Invoke():上調度線程

System.InvalidOperationException了未處理 消息:類型的未處理的異常「System.InvalidOperationException '發生在WindowsBase.dll 附加信息:調用線程不能訪問此對象,因爲不同的線程擁有它。

不夠公平 - 解決此問題的標準方法是使用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

嘗試將Thread.CurrentThread與App.Current.Dispatcher.Thread進行比較。很難判斷你是否在調度程序線程上運行,而沒有看到你正在調用window.Show()的完整方法。 – 2014-09-19 12:19:33

+0

對於這樣的問題,您無法獲得有用的答案。無益的做法是[這一個](http://blogs.msdn.com/b/calvin_hsia/archive/2007/12/12/6749902.aspx)。 – 2014-09-19 13:14:11

+0

我試過Application.Current.Dispatcher和Dispatcher.CurrentDispatcher - 它們是一樣的。我已更新帖子以消除歧義。 – roomaroo 2014-09-19 14:09:59

回答

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 }

+1

良好的通話。第一種情況給出{Current = System.Windows.Threading.SynchronizationContext}而不是null,但它不是DispatcherSynchronizationContext。 – roomaroo 2014-09-19 15:13:43

+1

http://referencesource.microsoft.com/WindowsBase/R/4990431309c71f1a.html上的代碼顯示Dispatcher在調用Action之前更改了SynchronizationContext。 – roomaroo 2014-09-19 15:14:53

+0

我遇到類似原始問題的東西,並尋找調試方法。不幸的是,在這兩種情況下,我都沒有看到current = null。查看哪個線程擁有我的對象的正確方法是什麼? – Adam 2017-05-06 09:25:46