Как сохранить консольное приложение .NET?

c# multithreading sleep manualresetevent

40806 просмотра

8 ответа

Рассмотрим консольное приложение, которое запускает некоторые службы в отдельном потоке. Все, что нужно сделать, это дождаться, пока пользователь нажмет Ctrl + C, чтобы выключить его.

Что из следующего является лучшим способом сделать это?

static ManualResetEvent _quitEvent = new ManualResetEvent(false);

static void Main() {
    Console.CancelKeyPress += (sender, eArgs) => {
        _quitEvent.Set();
        eArgs.Cancel = true;
    };

    // kick off asynchronous stuff 

    _quitEvent.WaitOne();

    // cleanup/shutdown and quit
}

Или это, используя Thread.Sleep (1):

static bool _quitFlag = false;

static void Main() {
    Console.CancelKeyPress += delegate {
        _quitFlag = true;
    };

    // kick off asynchronous stuff 

    while (!_quitFlag) {
        Thread.Sleep(1);
    }

    // cleanup/shutdown and quit
}
Автор: intoOrbit Источник Размещён: 12.11.2019 09:50

Ответы (8)


60 плюса

Решение

Вы всегда хотите запретить использование циклов while, особенно когда вы заставляете код перепроверять переменные. Это тратит ресурсы процессора и замедляет вашу программу.

Я бы определенно сказал первый.

Автор: Mike Размещён: 06.04.2010 04:48

27 плюса

В качестве альтернативы, более простое решение просто:

Console.ReadLine();
Автор: Cocowalla Размещён: 06.04.2010 04:49

13 плюса

Вы можете сделать это (и удалить CancelKeyPressобработчик события):

while(!_quitFlag)
{
    var keyInfo = Console.ReadKey();
    _quitFlag = keyInfo.Key == ConsoleKey.C
             && keyInfo.Modifiers == ConsoleModifiers.Control;
}

Не уверен, что так лучше, но мне не нравится идея вызова Thread.Sleepв цикле ... Я думаю, что чище блокировать ввод пользователя.

Автор: Thomas Levesque Размещён: 06.04.2010 04:51

9 плюса

Я предпочитаю использовать Application.Run

static void Main(string[] args) {

   //Do your stuff here

   System.Windows.Forms.Application.Run();

   //Cleanup/Before Quit
}

из документов:

Начинает запуск стандартного цикла сообщений приложения в текущем потоке без формы.

Автор: ygaradon Размещён: 10.11.2014 11:46

3 плюса

Похоже, вы делаете это сложнее, чем нужно. Почему бы не просто Joinпоток после того, как вы дали сигнал, чтобы остановить?

class Program
{
    static void Main(string[] args)
    {
        Worker worker = new Worker();
        Thread t = new Thread(worker.DoWork);
        t.IsBackground = true;
        t.Start();

        while (true)
        {
            var keyInfo = Console.ReadKey();
            if (keyInfo.Key == ConsoleKey.C && keyInfo.Modifiers == ConsoleModifiers.Control)
            {
                worker.KeepGoing = false;
                break;
            }
        }
        t.Join();
    }
}

class Worker
{
    public bool KeepGoing { get; set; }

    public Worker()
    {
        KeepGoing = true;
    }

    public void DoWork()
    {
        while (KeepGoing)
        {
            Console.WriteLine("Ding");
            Thread.Sleep(200);
        }
    }
}
Автор: Ed Power Размещён: 07.04.2010 05:43

2 плюса

Из двух первых лучше

_quitEvent.WaitOne();

потому что во втором поток просыпается каждую миллисекунду и будет включен в прерывание ОС, что дорого

Автор: Naveen Размещён: 06.04.2010 04:50

0 плюса

Вы должны делать это так же, как если бы вы программировали службу Windows. Вы никогда не будете использовать оператор while, вместо этого вы будете использовать делегат. WaitOne () обычно используется при ожидании удаления потоков - Thread.Sleep () - не рекомендуется. Задумывались ли вы об использовании System.Timers.Timer с помощью этого события для проверки на событие завершения работы?

Автор: KenL Размещён: 06.04.2010 05:22

0 плюса

Также возможно заблокировать поток / программу на основе токена отмены.

token.WaitHandle.WaitOne();

WaitHandle сигнализируется, когда токен отменен.

Я видел эту технику, используемую в Microsoft.Azure.WebJobs.JobHost, где токен происходит из источника токена отмены WebJobsShutdownWatcher (наблюдатель файла, который завершает задание).

Это дает некоторый контроль над тем, когда программа может закончиться.

Автор: CRice Размещён: 22.01.2019 05:21
Вопросы из категории :
32x32