2010-10-06 32 views
0

在閱讀了幾篇文章後,我仍然不確定我是否理解了多線程來解決我的特定問題。如何在主窗體中等待工作線程?

我有一個主窗體將啓動一個後臺工作線程(工人)。工作者線程將執行一個While(!Stopping)無限循環,並且將在每次迭代結束時通過全局Stopping對象(只讀鎖對象)終止睡眠。當用戶按下「停止」按鈕時工作正常, 工作人員將在當前迭代後停止。

現在我想要當用戶關閉主窗體時,它會先設置停止標誌,讓工作線程 完成當前的工作。之後,主表單將關閉。似乎很簡單,但我無法使其工作。

我試過了worker.Join(),或者在while循環中測試了woker.IsAlive,但是這兩種情況都會在幾秒後因爲某種原因鎖定應用程序(主窗體)?

以下是我的代碼Form_Closing事件處理中(不工作):

   // Tell the thread to stop the file 
       Stop(); 
       Logger.Info("Stopping the thread by Close the application"); 
       //Not working as well      
       //worker.Join(); 
       while (worker.IsAlive) 
       { 
        Thread.Sleep(5000); 
        Logger.Info("After sleep for 5 seconds"); 
       } 
       Logger.Info("worker thread stopped"); 

一件事有趣的是,工作線程似乎總是寫日誌事件,直到每個循環迭代,那麼剩下的結束日誌條目將在 while(worker.IsAlive)循環內部成爲主窗體事件。

回答

2

Join會一直等待線程,在UI線程中使用它會使應用程序看起來被鎖定。 IsAlive不會阻塞GUI線程中的任何內容,它是您的Thread.Sleep。

做somethnig這樣,而不是:

while (worker.IsAlive) 
{ 
    Thread.sleep(50); 
    Application.DoEvents(); 
} 
+0

謝謝,這個解決方案似乎運作良好。 – 2010-10-06 21:40:50

0

您正在創建一個死鎖,以某種方式在您請求的任何位置放置一個斷點並釋放鎖定對象。您也可以使用system.threading.monitor類來測試鎖是否可用,而不是創建死鎖。非常熟悉VS中的線程窗口。

+0

不幸的是,這是我們第一個需要.NET 4.0的項目,因此我目前正在使用VS2010 Express。看起來不像它有調試線程窗口。 – 2010-10-06 21:47:49

0

請記住,您使用導致UI線程暫停其正常抽水消息義務的任何代碼都自己表現爲一個掛給用戶。換句話說,不叫這可能會阻止包括Thread.JoinThread.SleepWaitHandle.WaitOne,任何方法等

既然你想要的工人在封閉的形式,那麼我建議讓形式停止信號已發出結束後終止到工作者線程。致電Application.Run後,請致電Thread.Join致電您的應用程序的入口點。由於您正在關閉應用程序,因此如果線程沒有及時響應,可以致電Thread.Abort。這裏是一些示例代碼。

public void Main(string[] args) 
{ 
    var form = new YourForm(); 
    Application.Run(form); 
    if (!form.WorkerThread.Join(TIME_TO_WAIT)) 
    { 
    form.WorkerThread.Abort(); 
    } 
} 
+0

感謝Brian Gideon,我測試了您的解決方案,但我的主表單將立即關閉。問題在於我並沒有真正理解你的解決方案,我不確定我是否以正確的方式實施了它。 – 2010-10-06 22:01:52

+0

基本上我現在只需調用Stop()在窗體的關閉事件中爲工作線程設置停止標誌。我認爲在這一點上我的主窗體將被關閉,執行將返回到program.cs的行:if(!form.WorkerThread。加入(TIME_TO_WAIT)),但是因爲主窗體在那一點關閉了,並且似乎Logger函數也沒有從那一點開始工作,所以我怎麼知道從那一點發生了什麼? – 2010-10-06 22:11:07