How to save a .NET console application?

Consider a console application that runs some services in a separate thread. All you have to do is wait for the user to press Ctrl + C to close it.

Which of the following is the best way to do this?

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 } 

Or this using 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 } 
+86
multithreading c # sleep manualresetevent
Apr 6 '10 at 16:45
source share
8 answers

you always want to prevent the use of while loops, especially when you force code to double-check variables. It spends processor resources and slows down your program.

I would definitely say first.

+54
Apr 6 2018-10-16T00:
source share

Alternatively, a simpler solution is simply:

 Console.ReadLine(); 
+26
Apr 6 2018-10-06T00:
source share

You can do this (and remove the CancelKeyPress event CancelKeyPress ):

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

Not sure if this is better, but I don't like the idea of ​​calling Thread.Sleep in a loop. I think it’s cleaner to block on user input.

+11
Apr 6 2018-10-16T00:
source share

I prefer to use Application.Run

 static void Main(string[] args) { //Do your stuff here System.Windows.Forms.Application.Run(); //Cleanup/Before Quit } 

from documents:

Begins a standard application message loop in the current formless stream.

+8
Nov 10 '14 at 11:46
source share

It looks like you are making it harder than you need. Why not just Join thread after you stop it?

 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); } } } 
+3
Apr 07 2018-10-17T00:
source share

Of the first two, it’s better

 _quitEvent.WaitOne(); 

because in the second, a thread that wakes up every millisecond will turn into an OS interrupt, which is expensive

+2
Apr 6 '10 at 16:50
source share

You should do this as if you were programming a Windows service. You would never use a while statement; instead, you would use a delegate. WaitOne () is usually used while waiting for threads to kill - Thread.Sleep () is impractical. Have you thought to use System.Timers.Timer using this event to check for a closing event?

0
Apr 6 2018-10-06T00:
source share

It is also possible to block a thread / program based on a cancel token.

 token.WaitHandle.WaitOne(); 

WaitHandle is signaled when the token is canceled.

I saw this technique used by Microsoft.Azure.WebJobs.JobHost, where the token comes from the source of the WebJobsShutdownWatcher cancellation token (the file watcher that completes the job).

This gives some control over when a program can end.

0
Jan 22 '19 at 5:21
source share



All Articles