Использование семафора вместо цикла while. Хорошо это или плохо?

У меня есть процесс, который выполняется в собственном потоке и может быть запущен / остановлен без блокировки. В конечном итоге это перейдет в службу Windows, но пока я настраиваю это в консольном приложении, пока оно не будет полностью реализовано.

После вызова Start () я хочу, чтобы основной поток программы блокировался до тех пор, пока не будет нажата Ctrl-C. Я знаю, что это сработает:

public static void Main(string[] args)
{
    bool keepGoing = true;

    var service = new Service();

    System.Console.TreatControlCAsInput = false;

    System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
    {
        e.Cancel = true;
        service.Stop();
        keepGoing = false; // Break the while loop below
    };

    service.Start();

    while( keepGoing )
    {
        Thread.Sleep(100); // 100 is arbitrary
    }

}

Однако меня надоедают флаг и произвольное значение сна. Я знаю, что стоимость ЦП практически равна нулю в цикле while, но я бы предпочел иметь «жесткий» блок, который освобождается, как только будет выполнен обработчик Ctrl-C.Я разработал следующее, используя семафор для блокировки, пока не будет выполнен анонимный обработчик Ctrl-C:

public static void Main(string[] args)
{
    var service = new Service();

    var s = new Semaphore(1, 1);

    System.Console.TreatControlCAsInput = false;

    System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
    {
        e.Cancel = true;
        service.Stop();
        s.Release(); // This will allow the program to conclude below
    };

    service.Start();

    s.WaitOne(); // This will not block
    s.WaitOne(); // This will block w/o CPU usage until the sempahore is released

}

Это плохой дизайн? Это излишество? Это опасно?

РЕДАКТИРОВАТЬ:

Я также подключаю AppDomain.CurrentDomain.UnhandledException следующим образом:

AppDomain.CurrentDomain.UnhandledException += delegate {
  service.Stop();
  s.Release();
};

ИЗМЕНИТЬ 2-е:

Я должен отметить, что очень важно, чтобы Stop () метод вызывается при выходе. @Adam Ralph имеет совершенно хороший шаблон для гибридной консоли / сервиса, но у него не было этой информации при ответе на вопрос.

6
задан Chris Simmons 2 December 2011 в 14:01
поделиться