Suppose you need to write a console application that will run as a scheduled task on a busy production server, but you want to delay the exit so that they can read the results on the screen, but not force someone to push a key, as there may not always be someone at the console to do so. Ending with Console.ReadKey() is no good as it will wait until you push a key before it exits. Here is my solution:
1 using System;
2 using System.Threading;
3
4 namespace ConsoleApplication1
5 {
6 class Program
7 {
8 static void Main(string[] args)
9 {
10 //... code here for whatever your console app does
11
12 Console.WriteLine("Press any key to exit...");
13
14 delay = new ExitDelay();
15 delay.Start();
16 MyTimer = new Timer(TimesUp, null, 10000, Timeout.Infinite);
17 }
18
19 static ExitDelay delay;
20 static Timer MyTimer;
21
22 // Timer callback: they didn't press any key, but we don't want this window open forever!
23 private static void TimesUp(object state)
24 {
25 delay.Stop();
26 MyTimer.Dispose();
27 Environment.Exit(0);
28 }
29
30 }
31
32 public class ExitDelay
33 {
34 private readonly Thread workerThread;
35
36 public ExitDelay()
37 {
38 this.workerThread = new Thread(this.work);
39 this.workerThread.Priority = ThreadPriority.Lowest;
40 this.workerThread.Name = "ExitTimer";
41 }
42
43 public void Start()
44 {
45 this.workerThread.Start();
46 }
47
48 public void Stop()
49 {
50 this.workerThread.Abort();
51 }
52
53 private void work()
54 {
55 Console.ReadKey();
56 this.Stop();
57 }
58 }
59
60 }
This gives someone 10 seconds to read the result and press a key before exiting the application automatically.
Edit: A newer Version of this technique us available . The new Version provides an on screen countdown, notifying the user that the program is about to exit - otherwise if there is someone at the console and it suddenly quits while instructing them to hit any key to quit, that might be a bit worrying! I leave this example here because it is a good example of how start and stop a new Thread as well as how to use the System.Threading.Timer Class in a slightly different way to the new version which uses polling.