[c#] .NET 콘솔 앱을 계속 실행하는 방법은 무엇입니까?

별도의 스레드에서 일부 서비스를 시작하는 콘솔 애플리케이션을 고려하십시오. 사용자가 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
}



답변

특히 코드에서 변수를 다시 확인하도록 할 때 항상 while 루프를 사용하지 않으려 고합니다. CPU 리소스를 낭비하고 프로그램 속도를 늦 춥니 다.

나는 확실히 첫 번째를 말할 것입니다.


답변

또는 더 간단한 솔루션은 다음과 같습니다.

Console.ReadLine();


답변

그렇게 할 수 있습니다 (그리고 CancelKeyPress이벤트 핸들러를 제거하십시오 ).

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

그게 더 좋은지는 모르겠지만 Thread.Sleep루프에서 호출한다는 생각이 마음에 들지 않습니다 . 사용자 입력을 차단하는 것이 더 깔끔하다고 생각합니다.


답변

나는 Application.Run을 사용하는 것을 선호합니다.

static void Main(string[] args) {

   //Do your stuff here

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

   //Cleanup/Before Quit
}

문서에서 :

양식없이 현재 스레드에서 표준 응용 프로그램 메시지 루프 실행을 시작합니다.


답변

필요한 것보다 더 어렵게 만드는 것 같습니다. 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);
        }
    }
}


답변

취소 토큰을 기반으로 스레드 / 프로그램을 차단할 수도 있습니다.

token.WaitHandle.WaitOne();

WaitHandle은 토큰이 취소되면 신호를 보냅니다.

Microsoft.Azure.WebJobs.JobHost에서이 기술을 사용하는 것을 보았습니다. 여기서 토큰은 WebJobsShutdownWatcher (작업을 종료하는 파일 감시자)의 취소 토큰 소스에서 가져옵니다.

이것은 프로그램이 언제 종료 될 수 있는지에 대한 제어를 제공합니다.


답변

첫 번째 두 개 중 하나가 더 좋습니다

_quitEvent.WaitOne();

두 번째에서 스레드는 매 1 밀리 초마다 깨어나 기 때문에 비용이 많이 드는 OS 인터럽트로 전환됩니다.