When you write a console application, do you simply put
Console.WriteLine("Hit <enter> to end");
Console.ReadLine();
at the end of Main and block on Console.ReadLine()?
It’s much nicer to to make your console application work with Windows command line conventions and exit when the user types Control-C.
The Console class has a static event CancelKeyPress that fires when Ctrl-C is pressed. You can create an AutoResetEvent that blocks until you call Set in the CancelKeyPress handler.
It’s also nice to stop the application from being arbitrarily killed at the point where Ctrl-C is pressed by setting the EventArgs.Cancel property to true. This gives you a chance to complete what you are doing and exit the application cleanly.
Here’s an example. My little console application kicks off a worker thread and then blocks waiting for Ctrl-C as described above. When Ctrl-C is pressed I send a signal to the worker thread telling it to finish what it’s doing and exit.
using System;
using System.Threading;
namespace Mike.Spikes.ConsoleShutdown
{
class Program
{
privatestaticbool cancel = false;
staticvoid Main(string[] args)
{
Console.WriteLine("Application has started. Ctrl-C to end");
// do some cool stuff here
var myThread = new Thread(Worker);
myThread.Start();
var autoResetEvent = new AutoResetEvent(false);
Console.CancelKeyPress += (sender, eventArgs) =>
{
// cancel the cancellation to allow the program to shutdown cleanly
eventArgs.Cancel = true;
autoResetEvent.Set();
};
// main blocks here waiting for ctrl-C
autoResetEvent.WaitOne();
cancel = true;
Console.WriteLine("Now shutting down");
}
privatestaticvoid Worker()
{
while (!cancel)
{
Console.WriteLine("Worker is working");
Thread.Sleep(1000);
}
Console.WriteLine("Worker thread ending");
}
}
}
Much nicer I think.