2012-09-23 72 views
0

我在玩AutoResetEvent和我的應用程序沒有結束,我想我知道爲什麼:線程仍在運行,因此該應用程序不會終止。通常,在Main()中,按下一個鍵後,應用程序終止。但控制檯窗口不再關閉。我有一個簡單的控制檯應用程序:正確的方式來停止應用程序,而線程正在等待WaitOne()

private static EventWaitHandle waitHandle = new AutoResetEvent(false); 

    static void Main(string[] args) 
    { 
     AutoResetEventFun(); 

     Console.WriteLine("Press any key to end."); 
     Console.ReadKey(); 

     waitHandle.Close(); // This didn't cause the app to terminate. 
     waitHandle.Dispose(); // Nor did this. 
    } 

    private static void AutoResetEventFun() 
    { 
     // Start all of our threads. 
     new Thread(ThreadMethod1).Start(); 
     new Thread(ThreadMethod2).Start(); 
     new Thread(ThreadMethod3).Start(); 
     new Thread(ThreadMethod4).Start(); 

     while (Console.ReadKey().Key != ConsoleKey.X) 
     { 
      waitHandle.Set(); // Let one of our threads process. 
     } 
    } 

    // There are four of these methods. Only showing this one for brevity. 
    private static void ThreadMethod1() 
    { 
     Console.WriteLine("ThreadMethod1() waiting..."); 

     while (true) 
     { 
      waitHandle.WaitOne(); 
      Console.WriteLine("ThreadMethod1() continuing..."); 
     } 
    } 

什麼是正確的方式來終止此應用程序?我是否需要保留對每個線程的引用並在每個線程上調用Abort()?有沒有辦法表示waitHandle,以便等待它的線程終止? (我不這麼認爲,但我認爲這值得提問)。

回答

6

儘管我並不完全確定你要完成的任務,但終止此應用程序的一種方法是使所有線程背景主題:

private static void ThreadMethod1() 
{ 
    Thread.CurrentThread.IsBackground = true; 
    Console.WriteLine("ThreadMethod1() waiting..."); 

    while (true) 
    { 
     waitHandle.WaitOne(); 
     Console.WriteLine("ThreadMethod1() continuing..."); 
    } 
} 
+1

只要努力學習,就是這樣。 :)你的建議工作。這似乎是這個簡單的例子的路要走。謝謝! –

+2

沒問題!我們都在學習一點:)我不認爲你通常會在永不終止的線程中使用這些信號機制。我認爲一個更常見的用例是當你有一個線程做一些工作,但不能繼續下去,直到其他地方發生其他事情。一旦發生事情,它會恢復並完成其工作。後臺線程解決方案仍然很好知道,這是線程的一個重要方面。最後一件事,手動創建的線程默認爲Foreground,而ThreadPool線程默認爲後臺線程。 – BFree

+0

我在C#文章中關注了Joseph Albahari的Threading,我想嘗試使用'AutoResetEvent'。然後我搜索了一個實際的理由來使用它,並從Skeet先生那裏找到了這個:http://stackoverflow.com/questions/7735809/autoresetevent-and-manualresetevent。感謝您的小費。每一位都有幫助... –

1

另一種方法是設置一個波動「中止」布爾標誌,線程從的WaitOne回國後經常檢查()調用,看看他們是否需要退出。然後你可以設置這個標誌併發信號給WaitHandle [no。的時間。

+0

我喜歡這種方式,因爲它讓線程有機會正常退出,但是在主線程中,我不能只調用'waitHandle.Set()'四次並退出,因爲主線程退出之前*一些*線程有機會停止。主線程需要知道什麼時候所有其他線程完成之前關閉。+1一個很好的提示,但是。謝謝! –

+0

我一直在努力試圖讓這個權利,和我遇到了另一個問題。如果我四次調用waitHandle.Set(),它發生得如此之快,以至於一個線程可能受到兩個Set()調用的影響。這意味着另一個線程永遠不會應用Set()。 –

+0

我通過循環線程解決了這個問題。如果任何線程處於活動狀態,則調用Set(),Thread.Sleep(100),並保持循環,直到沒有更多線程處於活動狀態。所以,很好的建議,但它比簡單地調用Set()四次更復雜一點。 –

相關問題