2012-09-23 4 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

Нет проблем! Мы все учимся в один момент :) Я не думаю, что вы обычно используете эти механизмы сигнализации в потоках, которые никогда не заканчиваются. Я думаю, что более распространенный случай использования - когда у вас есть поток, который выполняет какую-то работу, но не может продолжаться до тех пор, пока что-то еще не произойдет в другом месте. Как только это произойдет, оно возобновляет и заканчивает работу. Решение Background Thread по-прежнему хорошо известно, это важный аспект Threads. Одна последняя вещь, созданная вручную Threads Forefront по умолчанию, а потоки ThreadPool - по умолчанию. – BFree

+0

Я следовал за Джозефом Альбахари Threading в статье C#, и я хотел попробовать использовать 'AutoResetEvent'. Затем я искал практическую причину, чтобы использовать его, и нашел это от мистера Скита: http://stackoverflow.com/questions/7735809/autoresetevent-and-manualresetevent. Спасибо за советы. Каждый бит помогает ... –

1

Другой путь состоит в летучий булев флаге «ABORT», что нити всегда проверять после возвращения из WaitOne() вызова, чтобы увидеть, если они должны выйти. Затем вы можете установить этот флаг и сигнализировать WaitHandle [no. потоков] раз.

+0

Мне нравится этот подход, потому что он дает потокам возможность выйти изящно. Однако в основном потоке я не могу просто вызвать 'waitHandle.Set()' четыре раза и выйти, потому что основной поток затем выходит до того, как * некоторые * из потоков имеют шанс остановиться. Основной поток должен знать, когда все остальные потоки выполняются до закрытия. +1 для хорошего подсказки. Спасибо! –

+0

Я работаю над пытаясь добиться этого, и Я столкнулся с другой проблемой. Если я вызываю waitHandle.Set() четыре раза, это происходит так быстро, что на один поток может влиять два вызова Set(). Это означает, что для другой нити не применяется Set(). –

+0

Я решил это, перейдя через потоки. Если какой-либо поток жив, я вызываю Set(), Thread.Sleep (100) и продолжаю цикл, пока не будет больше нитей. Итак, хорошее предложение, но это было немного сложнее, чем просто вызвать Set() четыре раза. –

 Смежные вопросы

  • Нет связанных вопросов^_^