2010-09-21 173 views
11

當我從工作線程調用UI線程時,發生死鎖。事實上,工作線程被阻塞在調用行:從工作線程調用UI線程時發生死鎖

return (ucAvancementTrtFamille)mInterfaceTraitement.Invoke(d, new object[] { psFamille }); 

奇怪的是,在UI線程(其中,糾正我,如果我錯了,是主線程)處於閒置狀態。

有沒有什麼辦法:

  1. 看到哪個線程實際上,我試圖調用?
  2. 看看線程真的在幹什麼?

我們可以在下圖中看到工作線程(ID 3732)在Invoke行上被阻塞,並且MainThread在應用程序的主函數中處於空閒狀態。

alt text

編輯:這是主線程的堆棧:

alt text

EDIT2:其實,我暫停了該計劃第二次,這裏是堆棧的樣子:

alt text

EDIT3:發現解決方法

我終於找到了解決方法。問題顯然是由於異步包裝競賽 條件問題。解決方法是使用BeginInvoke並等待它超時。當它超時時,再次調用並循環直到它最終返回。大多數情況下,它實際上是在第二個電話上工作。

IAsyncResult ar = mInterfaceTraitement.BeginInvoke(d, new object[] { psFamille }); 
      while (!ar.AsyncWaitHandle.WaitOne(3000, false)) 
      { 
       ar = mInterfaceTraitement.BeginInvoke(d, new object[] { psFamille }); 
      } 
      // Async call has returned - get response 
      ucAvancementTrtFamille mucAvancementTrtFamille = (ucAvancementTrtFamille)mInterfaceTraitement.EndInvoke(ar); 

這不是很漂亮,但它是我發現的唯一解決方案。

+0

你可以發佈'd'委託人在做什麼嗎? – 2010-09-21 17:46:14

+0

這是一個WinForms或WPF應用程序,對吧? – 2010-09-21 17:48:27

+0

委託只是創建一個圖形控件(在這一點上它甚至不會將它添加到任何形式)。我使用WinForms。 – leo 2010-09-22 07:46:37

回答

5

主線程不顯示空閒。您的屏幕截圖顯示了它在ECM.Program.Main上的當前位置。這是不正確的,如果它是空閒的,那麼它在Application.Run()中,抽取消息循環。這是Invoke()完成所需的。

雙擊主線程並切換到「調用堆棧」窗口,以查明它真的在做什麼。

+0

嗯,你是對的:它在我的ECM.Program.Main中的Application.Run()中。看我的編輯:它顯示主線程的堆棧。 – leo 2010-09-22 07:33:34

+0

是的,看起來它也是抽向我。粗。設置Symbol Server,啓用非託管代碼調試並向我們顯示死鎖線程的調用堆棧。 – 2010-09-22 12:02:29

+0

看來,異步包裝有一個競爭條件問題。使用我找到的解決方法查看我的第三個編輯。 – leo 2010-09-23 09:09:45

2

您是否嘗試過使用BeginInvoke而不是InvokeBeginInvoke是異步的。

+0

但調用應該工作 – Andrey 2010-09-21 16:56:30

+0

是的,但是'BeginInvoke'不會阻塞調用者。這只是一個建議,雖然是的,這應該不重要。 – 2010-09-21 16:58:31

+1

SimpleCoder,OP想要從Invoke返回值。 BeginInvoke不能代替這裏。 – 2010-09-21 17:47:13

0

您是否嘗試過使用BackgroundWorker來代替。如果你使用它,它會爲你節省很多這種Invoke和InvokeRequired調用。
我相信如果你創建一個新的線程並讓它執行你所顯示的那一行,你就不會有死鎖。我會嘗試找到我的舊代碼並將其發佈在此處。

2

你是對的。主線程是應用程序的入口點,通常是Application.Run的調用位置,它將使消息循環繼續。所以這應該是UI線程,除非你在消息循環方面做了不尋常的事情。

在線程窗口中,您可以右鍵單擊主線程,然後選擇切換以將調試上下文更改爲該線程。 Call Stack窗口將顯示當前執行方法的位置。

如果您的工作線程真的在Control.Invoke調用上被阻塞,並且UI線程處於空閒狀態,那麼您可能會遇到問題可能是由於正在封送的代理或消息循環中的指令執行尚未完成開始。後面看起來貌似合理,因爲你的屏幕顯示主線程的位置爲Main

+0

我正在編輯我的問題,並添加主線程的堆棧。我已啓用「顯示外部代碼」選項。 – leo 2010-09-22 07:36:23

0

您是否使用Visual Studio 2008? 如果答案是肯定的,你應該嘗試使用Visual Studio 2010.這是一個已知的錯誤。

祝你好運!