Cancelling Console.Read

 
 
  • Gérald Barré

Console.ReadLine and other read methods block the current thread until the user writes something in the console. Sometimes you want to cancel the read operation when a condition is met. For instance, you can cancel the read operation after a few seconds, or after receiving an event.

Windows provides a function to cancel an IO request: CancelIoEx. To use it, you must get the handle of the IO stream. In our case, it's the handle of the console input stream. You can get this handle by using GetStdHandle and the STD_INPUT_HANDLE constant. By combining the two functions, you can easily cancel a read request. Once the request is canceled, Console.Read throws an exception that you should handle. Depending on the read method used, you must catch the InvalidOperationException or the OperationCanceledException.

The following code starts a timer of 10 seconds and call Console.Read. If the user doesn't write anything, the timer cancel the IO request:

C#
class Program
{
    const int STD_INPUT_HANDLE = -10;

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CancelIoEx(IntPtr handle, IntPtr lpOverlapped);

    static void Main(string[] args)
    {
        // Start the timeout
        var read = false;
        Task.Delay(10000).ContinueWith(_ =>
        {
            if (!read)
            {
                // Timeout => cancel the console read
                var handle = GetStdHandle(STD_INPUT_HANDLE);
                CancelIoEx(handle, IntPtr.Zero);
            }
        });

        try
        {
            // Start reading from the console
            Console.WriteLine("Do you want to continue [Y/n] (10 seconds remaining):");
            var key = Console.ReadKey();
            read = true;
            Console.WriteLine("Key read");
        }
        // Handle the exception when the operation is canceled
        catch (InvalidOperationException)
        {
            Console.WriteLine("Operation canceled");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Operation canceled");
        }
    }
}

Documentation:

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub