Console.ReadKey canceling [duplicate]
Asked Answered
I

3

6

Possible Duplicate:
How to add a Timeout to Console.ReadLine()?

If I have a Console.ReadKey(), It makes the whole program stuck, how can I make it so that it will read a key for 1 second, and if a key is not read, something else would be set.

Incontrollable answered 17/1, 2013 at 17:48 Comment(5)
You get one question at a time. Pick one please.Trinatrinal
As sixlettervariables mentioned, you need to only ask one question at a time unless they are two parts of the same question. These are not. You should edit your question to remove one of your questions and rename the title.Chortle
similar to #58115Haemostatic
I am only a begginer in c#, so the code given to the guy in the link you gave me made 0 sense to me. Is there just a simple code that will wait make the Console.ReadKey command cancel out after a set amount of time?Incontrollable
@Incontrollable Even if you are a beginner you should learn how to do things correctly. if there is some aspect of the code you don't understand search msdn and other sites for documentation and examples. It's the only way to learn.Shuttering
E
12

The console has a property KeyAvailable. But your desired functionality (timeout) is not available. You could write your own function

private static ConsoleKeyInfo WaitForKey(int ms)
{
    int delay = 0;
    while (delay < ms) {
        if (Console.KeyAvailable) {
            return Console.ReadKey();
        }
        Thread.Sleep(50);
        delay += 50;
    }
    return new ConsoleKeyInfo((char)0, (ConsoleKey)0, false, false, false);
}

This function loops until the desired time in milliseconds has elapsed or a key has been pressed. It checks to see whether a key is available before it calls Console.ReadKey();. The check Console.KeyAvailable continues immediately, whether a key is available or not. It returns true if a key has been pressed and is ready to be read by ReadKey and false otherwise. If no key is available the function sleeps for 50 ms until it performs the next loop. This is better than looping without sleeping, because that would give you 100% CPU usage (on one core).

The function returns a ConsoleKeyInfo as ReadKey would, in case you want to know which key the user has pressed. The last line creates an empty ConsoleKeyInfo (see ConsoleKeyInfo Structure and ConsoleKeyInfo Constructor). It allows you to test whether the user pressed a key or whether the function timed out.

if (WaitForKey(1000).KeyChar == (char)0) {
    // The function timed out
} else {
    // The user pressed a key
}
Eastereasterday answered 17/1, 2013 at 18:13 Comment(7)
Well, this it does the job, mind explaining how this works?Incontrollable
Added explanation. (Sorry, I thought it was obvious).Eastereasterday
How does the Console.KeyAvailable works? and what does the long line in the end means (and what is that false,false,false?)?Incontrollable
Added some more explanations.Eastereasterday
I'm messing with the Console.KeyAvailable, How can I reset it so it wont be true forever?Incontrollable
if KeyAvailable is true you can call ReadKey. ReadKey sets KeyAvailable to false. If the user pressed more than one key, you could add this after the call to WaitForKey: while (Console.KeyAvailable) { ReadKey(); }Eastereasterday
Or you could do this: while (WaitForKey(1000).KeyChar != (char)0) { }. This waits one more second every time the user presses a key until the user does not press any key for one second or more.Eastereasterday
M
6
static ConsoleKeyInfo? MyReadKey()
{
    var task = Task.Run(() => Console.ReadKey(true));
    bool read = task.Wait(1000);
    if (read) return task.Result;
    return null;
}

var key = MyReadKey();
if (key == null)
{
    Console.WriteLine("NULL");
}
else
{
    Console.WriteLine(key.Value.Key);
}
Muslin answered 17/1, 2013 at 18:22 Comment(1)
The Task is never disposed which i think leads to unusable ThreadPool threads...Byrn
M
1

Do you mean something like this?

    Console.WriteLine("Waiting for input for 10 seconds...");

    DateTime start = DateTime.Now;

    bool gotKey = false;

    while ((DateTime.Now - start).TotalSeconds < 10)                
    {
        if (Console.KeyAvailable)
        {
            gotKey = true;
            break;
        }            
    }

    if (gotKey)
    {
        string s = Console.ReadLine();
    }
    else
        Console.WriteLine("Timed out");
Maomaoism answered 17/1, 2013 at 18:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.