2010-09-23 31 views
2

當我在UI線程上調用Thread.Sleep時,後臺線程中的所有調用方法是否會自動排隊到UI線程的消息泵中並在最終喚醒時進行處理?當UI線程正在休眠時,可以無限期地從後臺線程塊中調用方法嗎?

我遇到了使用大量線程池線程的Winform應用程序的問題,有時在鎖定/解鎖Windows之後應用程序掛起。一個猜測是在UI線程上發生了一些死鎖。另一個是一些UI控件是在後臺線程上創建的。 (這怎麼會導致任何問題???)

回答

1

規則是,只有創建一個UI控件的線程應該弄亂它。這就是「UI線程」的原因之一 - 它讓你無需猜測你是否需要Invoke的東西或只是做。 (如果事件發生在UI控件中,它在UI線程中,所以你可以這樣做,否則,Invoke。)所以你想在那個線程中創建你的控件,並讓它成爲處理所有UI的控件正如它打算的那樣。

您的用戶界面線程有一個目的:處理來自用戶界面的所有事件,以保持您的應用程序響應,並防止它看起來「凍結」。偶爾,它會很忙(處理其他事件),但它應該總是處理事件或等待另一個事件。 千萬不要在UI線程上調用Thread.Sleep,除非你有一個很好的理由,並可以明確說明爲什麼它不是一個可怕的想法。幾乎所有你想用Thread.Sleep做的事情都可以用定時器來處理,而不是那麼搖搖晃晃。

短版:是的,如果UI線程正在做某事(甚至是睡眠),對Control.Invoke的調用幾乎肯定會等到它不是。如果線程正在睡覺,那可能會很長時間。

1

是的,解鎖工作站時發生死鎖是一個相當臭名昭着的Windows窗體線程問題。我從來沒有得到一個很好的診斷,但我確信它是由SystemEvents類造成的。這是一個程序初始化問題,當控件開始訂閱它的事件時,類會根據需要進行初始化。

我認爲失敗模式是創建第一個形式在一個線程以外的程序的主線程。例如,當你創建自己的啓動畫面而不是使用.NET啓動畫面時,你會得到這個。或者旋轉一個創建自己的表單實例的線程,並儘快啓動它。結果,SystemEvents將從錯誤的線程中激發它的事件。 SystemSwitch事件以某種方式致命。

所以,用細齒梳看看你的啓動代碼。在做任何重要的事情之前,訂閱Main()方法中的一個系統事件應該是Q & D修復。

相關問題