2012-09-03 47 views
4

我們有一個嵌入在WinForms控件中的WPF控件,該控件又作爲ActiveX控件公開。該ActiveX最終用於由第三方開發的C++應用程序。WPF在WinForms中:在Dispatcher.Invoke上被阻塞,儘管UI線程在活

在某些時候,ActiveX控件的用戶界面變爲凍結狀態,而其餘的C++應用程序運行良好。經過一些調試後,我發現每次調用Application.Current.Dispatcher.Invoke時WPF控件都被阻塞了。但是,WinForms控件處理它的Control.Invoke的調用就好了。每當我暫停調試器時,我都可以看到UI線程正在C++應用程序中做一些工作,但似乎沒有被阻塞或等待任何東西。就好像UI線程突然莫名其妙地拒絕執行WPF代表。

當C++應用程序獨佔UI線程很長一段時間(幾分鐘)時,WPF控件有時會進入此狀態。我要做的第一件事就是使用一個不同的線程進行如此耗時的任務,但正如我已經說過的,我不對C++應用程序正在做什麼負責。無論如何,這不是我的WPF控件以這種方式行事的理由。我不知道如何解決這個問題,任何幫助,將不勝感激。

回答

0

Invoke的問題是它的行爲像多線程調用;但事實並非如此,Invoke正在屏蔽 - 您仍然一次只放一個線程。 Invoke確實只是確保在UI線程上執行操作。這是通過強制消息進入消息泵並以這種方式執行來完成的。該行爲可能會被阻止在線程調用Invoke需要做的事情,讓行動繼續。 例如:

lock(someLock) 
{ 
    dispatcher.Invoke(SomeMethod); 
} 

//... 

public void SomeMethod() 
{ 
    lock(someLock) 
    { 
    //... do some work here 
    } 
} 

在這個例子中,Invoke被阻塞調用SomeMethod同時保持一個鎖。但是,SomeMethod想要相同的lock,所以它被阻止等待lock。你有一個僵局。

我建議使用BeginInvoke來代替。

我不確定如果這是您的問題,因爲您沒有提供任何代碼;但這是一個非常Invoke的常見問題。通常沒有理由需要Invoke;如果您認爲有需要,那通常表明存在問題。

+0

謝謝你的回答彼得。在你的例子中,主線程將被阻塞在SomeMethod的鎖上。就我而言,它並沒有被阻塞。真的沒有理由爲什麼我應該卡在一個Invoke上。正如我所說,在同一線程的WinForm中的調用工作得很好。顯然,WPF Dispatcher由於某種原因不再響應。 – Odsh

+0

@odsh是的,這只是一個簡單的例子,你可以通過使用'Invoke'而不是'BeginInvoke'來獲得死鎖 - 儘管使用WinForms而不是WPF。 'Dispatcher.Invoke' /'BeginInvoke'也是如此。框架方法鎖定在許多你不瞭解也無法控制的地方 - 導致你遇到類似的情況。你嘗試過使用Dispatcher.BeginInvoke嗎? –

+0

我不能在我的應用程序中用BeginInvokes替換所有的調用;有時這個電話必須是同步的。無論如何,我認爲沒有死鎖,否則主線程將被阻塞 - 他不是。如果像你所說的那樣,框架方法在某個地方被阻塞了,我想理解爲什麼並且糾正了這個問題。放棄調用,因爲他們可以在我不知道的地方隨機導致死鎖,這對我來說不是一個解決方案。 – Odsh

1

我建議運行MS調試診斷工具 - http://support.microsoft.com/kb/2580960

我們已經有了很好的結果來識別COM互操作阻塞問題,在我們的案例中,這個問題歸結爲一個掛起的COM終結器阻塞垃圾收集。你可以在不同的模式下運行它,但是當運行.NET分析時,它會突出顯示終結者隊列中的任何問題等。運行它有點笨重,但它給你的信息是黃金。

相關問題