Поток сохраняется после завершения приложения из-за сигнала AutoResetEvent в состоянии WaitOne - PullRequest
3 голосов
/ 09 июля 2011

У меня есть приложение, которое использует AutoResetEvent (WaitOne / Set) в очереди для обработки сообщений.Я замечаю, что когда я завершаю сеанс отладки из Visual Studio (Shift + F5), оригинальный процесс для приложения зависает (но не всегда).Я вручную присоединяю отладчик к процессу и вижу, что в WaitHandle.WaitOne застрял один поток.

Итак, мой вопрос: как правильно завершить потоки, которые могут находиться в состоянии WaitOne?

Первый ответ, который всплыл в голову, это прослушать событие выхода приложения и выполнить там набор, но я не был уверен, было ли это событие надежно вызвано после этих сеансов отладки, или есть более стандартныйпрактика, о которой я не знаю.

И, как второй вопрос, не могли бы вы по-другому это обработать для приложения, работающего в «производственном» режиме?

Ответы [ 2 ]

4 голосов
/ 30 ноября 2012

Существует простой способ сделать это (не обходной путь)

Во-первых, вам нужно установить событие, которое будет срабатывать, когда ваше приложение умрет

// somewhere with global scope. On a singleton or in program class maybe
// this is set when you want to terminate your application
private static ManualResetEvent ExitWaitHandle = new ManualResetEvent(false);

А вот как это использовать в другом месте

// the event you want to check but it's blocking your application termination
private static AutoResetEvent yourEvent = new AutoResetEvent(true);

// the method where you have the problem
private static void FooAsync()
{
    try
    {
        WaitHandle.WaitAny(new WaitHandle[]{yourEvent, ExitWaitHandle});
        Checkpoint();

        // other stuff here

        // check if thread must die
        Checkpoint();
    }
    catch(ApplicationTerminatingException)
    {
        // thread must die, do cleanup and finalization stuff here
    }
    catch(Exception)
    {
        // holy cow! what should we do?
    }
}

private void CheckPoint()
{
    // fast check if the exit handle is set
    if(ExitWaitHandle.WaitOne(0))
    {
        throw new ApplicationTerminatingException(); // custom exception
    }
}

Единственные издержки - после "некоторого" кода вам нужно установить контрольную точку, чтобы прервать ваш поток. Надеюсь, это то, что вы искали.

2 голосов
/ 09 июля 2011

Одним из решений является установка потока как фоновой нити с использованием свойства Thread.IsBackground.При установке в потоке этот поток не будет останавливать процесс для выхода.

Однако поток может быть прерван в любое время, что обычно приводит к неопределенному поведению в зависимости от того, что делает ваш поток.Лучший способ завершить поток, по моему скромному мнению, - дать сигнал потоку на выход, например, установив флаг выхода и установив WaitHandle и разбудив его, затем Join запустив поток.

...