Как Вы закрываете приложение, когда некоторый WaitHandle посреди вызова к WaitOne?

Есть ли стандартный способ закрыть приложение "чисто" в то время как некоторые WaitHandle объекты могут быть в состоянии текущего вызова блокирования к WaitOne?

Например, может быть фоновый поток, который вращается вперед в методе как это:

while (_request.WaitOne())
{
    try
    {
        _workItem.Invoke();
    }
    finally
    {
        OnWorkCompleted();
    }
}

Я не вижу очевидного способа избавиться от этого потока без вызова Thread.Abort (который от тому, что я понимаю, препятствуют). Вызов Close на _request объект ( AutoResetEvent), однако, выдаст исключение.

В настоящее время поток, который выполняет этот цикл, имеет IsBackground набор свойств к true, и таким образом, приложение, кажется, закрывается правильно. Однако с тех пор WaitHandle реализации IDisposable, Я не уверен, если это считают кошерным или если тот объект действительно должен быть расположен перед выходами приложения.

Действительно ли это - плохой дизайн? В противном случае, как с этим сценарием обычно имеют дело с?

8
задан Dan Tao 21 June 2010 в 19:11
поделиться

4 ответа

Определите дополнительный WaitHandle под названием _terminate, который будет сигнализировать о запросе на завершение цикла, а затем используйте WaitHandle.WaitAny вместо WaitHandle.WaitOne.

var handles = { _request, _terminate };
while (WaitHandle.WaitAny(handles) == 0)
{
  try
  {
    _workItem.Invoke();
  }
  finally
  {
    OnCompleteWork();
  }
}
8
ответ дан 5 December 2019 в 17:34
поделиться

Установите для свойства IsBackground значение true ... оно должно автоматически закрывать поток при завершении работы приложения.

Вы также можете прервать поток, вызвав Thread.Interrupt и обработав исключение ThreadInterruptedException . Другая идея - вызвать _request.Set () и заставить цикл while проверять изменчивый флаг, чтобы определить, закрывается ли приложение или должно ли оно продолжаться:

private volatile bool _running = true;
while(_request.WaitOne() && _running)
{
    //...
}

// somewhere else in the app
_running = false;
_request.Set();
1
ответ дан 5 December 2019 в 17:34
поделиться

Я думаю, что операционная система очистится после завершения вашего процесса. Поскольку ваш поток отмечен как IsBackground, среда CLR завершит процесс и все потоки внутри него, поэтому это не проблема.

0
ответ дан 5 December 2019 в 17:34
поделиться

Когда поток блокируется (независимо от того, что он блокирует), вы можете вызвать Thread.Interrupt () Это вызовет исключение ThreadInterruptedException (я считаю, что это может быть немного отличается) Вы можете обработать это исключение в самом потоке и выполнить любую необходимую очистку.

Стоит отметить, что поток будет генерировать исключение ThreadInterruptedException только тогда, когда он блокируется, если он не блокирует, он не будет сгенерирован до тех пор, пока не попытается выполнить блокировку в следующий раз.

Это «безопасный» способ завершить цепочку из того, что я читал по этой теме. Также стоит отметить

: если объект реализует как IDisposable, так и финализатор (что будет, если он использует неуправляемые ресурсы), GC вызовет финализатор, который обычно вызывает dispose. Обычно это недетерминированный. Однако вы можете гарантировать, что они будут вызваны при выходе из приложения. Только при очень особых обстоятельствах они бы этого не сделали. (Выдается исключение завершения среды .net, такое как StackOverflowException )

1
ответ дан 5 December 2019 в 17:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: