0

So let's use this code:

Console.ReadKey(true);
//Cancel the ReadKey prompt
Console.WriteLine("ReadKey was cancelled.");

Upon running the program, the only thing that should happen is that the output ReadKey was cancelled. should appear. How can I achieve this? Is it even possible?

Thanks in advance.

Adam
  • 612
  • 4
  • 13
  • 23
  • 4
    `ReadKey` is a synchronous, blocking call. The execution will not continue (the write line) until someone presses a key. The `true` indicates that whatever key was pressed should *not* be printed to the console's stdout. Then your write line will be called, and the program will immediately exit. (assuming this is literally the body of `Main`). – vcsjones Aug 18 '13 at 21:22
  • @vcsjones That's not what I asked. – Adam Aug 18 '13 at 21:59
  • 1
    what you are asking is not clear to me, hence why I posted a comment, not an answer. – vcsjones Aug 18 '13 at 22:03
  • I was asking how to abort the prompt for a key to be entered. My problem is that I have a constant check on ReadKey(), and when ReadLine() is called in a different thread, the first letter entered doesn't get registered. – Adam Aug 18 '13 at 22:04

3 Answers3

3

You can't cancel ReadKey, unless you abort the thread. (Force closing the program.)

I check if a key is available using the Console.KeyAvailable property before calling ReadKey.

Kayla
  • 485
  • 5
  • 14
  • 1
    But the problem isn't even to call it or not to call it.. It's to cancel it if it's running – Adam Aug 18 '13 at 22:13
  • If you loop checking `Console.KeyAvailable`, and only call `Console.ReadKey` if there is a key available, then it won't block, and it will return immediately – Flydog57 Aug 16 '22 at 22:10
1

The only way I can see you could do this is using System.Windows.Forms.SendKeys.Send(), however this doesn't work 'out of the box' for a console app because they don't manage windows messages, if you try it you'll see the exception. There could be a way to implement this yourself using windows API's.

Jim
  • 21
  • 1
0

Nearly 10 years later, how about doing it async? You still need to do it on another thread if you want to make it cancelable, but...

If you want a fully cancelable async version, here goes:

public static async Task<char?> ReadConsoleCharAsync(CancellationToken cancellationToken, bool intercept = false)
{
    // if there is a key available, return it without waiting
    //  (or dispatching work to the thread queue)
    if (Console.KeyAvailable)
    {
        var read = Console.ReadKey(intercept);
        return read.KeyChar;
    }

    // otherwise
    var result = await Task.Run<char?>(async () =>
    {
        while (!cancellationToken.IsCancellationRequested)
        {
            await Task.Delay(100);
            if (Console.KeyAvailable)
            {
                var read = Console.ReadKey(intercept);
                return read.KeyChar;
            }
        }
        cancellationToken.ThrowIfCancellationRequested();
        return null;
    }, cancellationToken);
    return result;
}

I return a char, but you could return the full ConsoleKeyInfo if you wanted.

If you want a non-cancellable async version, it's a bit simpler:

public static async Task<char> ReadConsoleCharAsync(bool intercept = false)
{
    // if there is a key available, return it without waiting
    //  (or dispatching work to the thread queue)
    if (Console.KeyAvailable)
    {
        var read = Console.ReadKey(intercept);
        return read.KeyChar;
    }

    // otherwise
    var result = await Task.Run<char>(async () =>
    {
        while (!Console.KeyAvailable)
        {
            await Task.Delay(100);
        }

        var read = Console.ReadKey(intercept);
        return read.KeyChar;
        
    });
    return result;
}

In both cases, I check to see if there's a character to read before doing anything else. If there is one, I return it. If not, I dispatch work to the threadpool using Task.Run. I need to return a char? in the cancellable case; I need to return something when it gets cancelled (so it's a null)

Flydog57
  • 6,851
  • 2
  • 17
  • 18