8

Suppose my console program performs multiple lengthy tasks. Between these tasks, I'd like it to pause - either for a few seconds or until any key gets pressed. (Whichever comes first.)

These criteria are easy to check on their own, but they refuse to get along when I try combining them: Either the timing mechanism pauses for a few seconds before ReadKey starts, or Readkey blocks out the thread entirely until satisfied. How can I satisfy both conditions?

4444
  • 3,541
  • 10
  • 32
  • 43
  • 3
    http://stackoverflow.com/questions/57615/how-to-add-a-timeout-to-console-readline – dugas Aug 02 '12 at 20:55
  • Any example available? This sounds like as if you can only notify main thread that this is done, then wait there until you can continue, keep track of any timer and stop it if keyboard pressed, but can't elaborate without example – Daniel MesSer Aug 02 '12 at 21:01

5 Answers5

21

One way to do this in C# 4.0:

Task.Factory.StartNew(() => Console.ReadKey()).Wait(TimeSpan.FromSeconds(5.0));
lesscode
  • 6,221
  • 30
  • 58
  • 2
    If you need to know the source, then just save the result of the `Wait` call to a bool variable. If it timed out, will return false, otherwise will return true (meaning there's a key available). – SPFiredrake Aug 02 '12 at 21:41
  • 3
    I should have added that you should probably only use this approach for short-lived console apps that don't have many steps, since each time the "timed out" path is taken, there will be a zombie thread sitting waiting for a key press. Don't try this inside a 10,000 count loop! – lesscode Aug 02 '12 at 21:47
  • @Wayne That is a good point, I hadn't thought about that. (And I do plan on using it many times) Should I take any steps to prevent them from piling up? – 4444 Aug 03 '12 at 14:36
  • 1
    How about something like this: http://hen.co.za/blog/2011/07/console-readkey-with-timeout/ – lesscode Aug 03 '12 at 15:12
3

One way to do this is without a timer at all. Create a loop that makes the thread sleep for say 25 milliseconds, and then checks whether a key has been pressed via Console.KeyAvailable (which is non-blocking), or until the time between DateTime.Now() and the time of start of the loop has exceeded the timeout.

ikh
  • 2,336
  • 2
  • 19
  • 28
2

Extending from ikh's answer I wanted a count down with mine

        var original = DateTime.Now;
        var newTime = original;

        var waitTime = 10;
        var remainingWaitTime = waitTime;
        var lastWaitTime = waitTime.ToString();
        var keyRead = false;
        Console.Write("Waiting for key press or expiring in " + waitTime);
        do
        {
            keyRead = Console.KeyAvailable;
            if (!keyRead)
            {
                newTime = DateTime.Now;
                remainingWaitTime = waitTime - (int) (newTime - original).TotalSeconds;
                var newWaitTime = remainingWaitTime.ToString();
                if (newWaitTime != lastWaitTime)
                {
                    var backSpaces = new string('\b', lastWaitTime.Length);
                    var spaces = new string(' ', lastWaitTime.Length);
                    Console.Write(backSpaces + spaces + backSpaces);
                    lastWaitTime = newWaitTime;
                    Console.Write(lastWaitTime);
                    Thread.Sleep(25);
                }
            }
        } while (remainingWaitTime > 0 && !keyRead);
Matt Vukomanovic
  • 1,392
  • 1
  • 15
  • 23
0

Start two threads. One listens for keypress and other waits for some time. Make main thread to wait unless any one is done. Then proceed and ignore other thread response. :)

Ankush
  • 2,454
  • 2
  • 21
  • 27
0

Something like this?

bool IsPaused;
bool IsKeyPaused;

void Pause(){}
void UnPause(){}

void KeyDown(){
    if(!IsPaused)
    {
        IsPaused = true;
        IsKeyPaused = true;
        Pause();
    }
}
void KeyUp(){
    if(IsKeyPaused)
    {
        IsPaused = false;
        IsKeyPaused = false;
        UnPause();
    }
}
void TimerPause(){
    if(!IsPaused)
    {
        IsPaused = true;
        Pause();
    }
}
void TimerEnd(){
     UnPause();
}
CodeDemen
  • 1,841
  • 3
  • 17
  • 30