2012-09-23 45 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()四次更复杂一点。 –