Как вы закроете приложение, когда некоторые WATHANDLE в середине вызова в Waitone?

StackOverflow https://stackoverflow.com/questions/3087683

Вопрос

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

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

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

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

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

Это плохой дизайн? Если нет, как этот сценарий обычно занимался?

Это было полезно?

Решение

Определите дополнительное WaitHandle называется _terminate это будет сигналить запрос, чтобы завершить петлю, а затем использовать WaitHandle.WaitAny вместо WaitHandle.WaitOne.

var handles = { _request, _terminate };
while (WaitHandle.WaitAny(handles) == 0)
{
  try
  {
    _workItem.Invoke();
  }
  finally
  {
    OnCompleteWork();
  }
}

Другие советы

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

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

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

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

Установить IsBackground имущество true... Он должен автоматически закрывать поток, когда ваше приложение заканчивается.

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

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

// somewhere else in the app
_running = false;
_request.Set();

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top