Console ReadKey async还是回调?

6 .net

我正在尝试按Q来退出控制台窗口中的内容.我不喜欢我目前的实施.有没有办法可以异步或使用回调从控制台获取密钥?

svi*_*ick 15

您可以Console.ReadKey()从另一个线程调用,以便它不会阻止您的主线程.(您可以使用.Net 4 Task或旧版本来Thread启动新线程.)

class Program
{
    static volatile bool exit = false;

    static void Main()
    {
        Task.Factory.StartNew(() =>
            {
                while (Console.ReadKey().Key != ConsoleKey.Q) ;
                exit = true;
            });

        while (!exit)
        {
            // Do stuff
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 使用Console.KeyAvailable避免使用该线程. (5认同)

小智 7

这是我的制作方法:

// Comments language: pt-BR
// Aguarda key no console
private static async Task<ConsoleKey> WaitConsoleKey ( ) {
    try {
        // Prepara retorno
        ConsoleKey key = default;
        // Aguarda uma tecla ser pressionada
        await Task.Run ( ( ) => key = Console.ReadKey ( true ).Key );
        // Retorna a tecla
        return key;
    }
    catch ( Exception ex ) {
        throw ex;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以使用KeyAvailable属性(Framework 2.0):

if (System.Console.KeyAvailable)
{
   ConsoleKeyInfo key = System.Console.ReadKey(true);//true don't print char on console
   if (key.Key == ConsoleKey.Q)
   {
       //Do something
   }
}
Run Code Online (Sandbox Code Playgroud)


Jod*_*ell 5

我没有发现任何完全令人满意的现有答案所以我自己写了,与TAP和.Net 4.5 一起工作.

/// <summary>
/// Obtains the next character or function key pressed by the user
/// asynchronously. The pressed key is displayed in the console window.
/// </summary>
/// <param name="cancellationToken">
/// The cancellation token that can be used to cancel the read.
/// </param>
/// <param name="responsiveness">
/// The number of milliseconds to wait between polling the
/// <see cref="Console.KeyAvailable"/> property.
/// </param>
/// <returns>Information describing what key was pressed.</returns>
/// <exception cref="TaskCanceledException">
/// Thrown when the read is cancelled by the user input (Ctrl+C etc.)
/// or when cancellation is signalled via
/// the passed <paramred name="cancellationToken"/>.
/// </exception>
public static async Task<ConsoleKeyInfo> ReadKeyAsync(
    CancellationToken cancellationToken,
    int responsiveness = 100)
{
    var cancelPressed = false;
    var cancelWatcher = new ConsoleCancelEventHandler(
        (sender, args) => { cancelPressed = true; });
    Console.CancelKeyPress += cancelWatcher;
    try
    {
        while (!cancelPressed && !cancellationToken.IsCancellationRequested)
        {
            if (Console.KeyAvailable)
            {
                return Console.ReadKey();
            }

            await Task.Delay(
                responsiveness,
                cancellationToken);
        }

        if (cancelPressed)
        {
            throw new TaskCanceledException(
                "Readkey canceled by user input.");
        }

        throw new TaskCanceledException();
    }
    finally
    {
        Console.CancelKeyPress -= cancelWatcher;
    }
}
Run Code Online (Sandbox Code Playgroud)