jille_Jr icon

[C#] Async console reading

jille_Jr | PRO | 12/28/18 01:47:17 PM UTC | 0 ⭐ | 431 👁️ | Never ⏰ | []
C# |

4.05 KB

|

None

|

0 👍

/

0 👎

using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
 
namespace System
{
    public static class AsyncConsole
    {
        /// <see href="https://docs.microsoft.com/en-us/windows/console/getstdhandle"/>
        private enum StdHandle
        {        
            STD_INPUT_HANDLE = -10,
            STD_OUTPUT_HANDLE = -11,
            STD_ERROR_HANDLE = -12
        }
 
        /// <see href="https://docs.microsoft.com/en-us/windows/console/getstdhandle"/>
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr GetStdHandle(int nStdHandle);
 
        /// <see href="https://docs.microsoft.com/en-us/windows/desktop/FileIO/cancelioex-func"/>
        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool CancelIoEx(IntPtr handle, IntPtr lpOverlapped);
 
        public static async Task<ConsoleKeyInfo> ReadKey(CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (RegisterReadCancel(cancellationToken))
            {
                return await Task.Run(() =>
                {
                    try
                    {
                        return Console.ReadKey();
                    }
                    catch (InvalidOperationException inner)
                    {
                        throw new OperationCanceledException("Operation cancelled.", inner, cancellationToken);
                    }
                }, cancellationToken);
            }
        }
 
        public static async Task<ConsoleKeyInfo> ReadKey(bool intercept, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (RegisterReadCancel(cancellationToken))
            {
                return await Task.Run(() =>
                {
                    try
                    {
                        return Console.ReadKey(intercept);
                    }
                    catch (InvalidOperationException inner)
                    {
                        throw new OperationCanceledException("Operation cancelled.", inner, cancellationToken);
                    }
                }, cancellationToken);
            }
        }
 
        public static async Task<string> ReadLine(CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (RegisterReadCancel(cancellationToken))
            {
                return await Task.Run(() =>
                {
                    try
                    {
                        return Console.ReadLine();
                    }
                    catch (InvalidOperationException inner)
                    {
                        throw new OperationCanceledException("Operation cancelled.", inner, cancellationToken);
                    }
                }, cancellationToken);
            }
        }
 
        public static async Task<int> Read(CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            using (RegisterReadCancel(cancellationToken))
            {
                return await Task.Run(() =>
                {
                    try
                    {
                        return Console.Read();
                    }
                    catch (InvalidOperationException inner)
                    {
                        throw new OperationCanceledException("Operation cancelled.", inner, cancellationToken);
                    }
                }, cancellationToken);
            }
        }
 
        private static CancellationTokenRegistration RegisterReadCancel(CancellationToken cancellationToken)
        {
            return cancellationToken.Register(() =>
            {
                IntPtr handle = GetStdHandle((int)StdHandle.STD_INPUT_HANDLE);
                CancelIoEx(handle, IntPtr.Zero);
            });
        }
    }
}

Comments