等待控制台应用程序中的键盘事件

时间:2017-07-18 16:40:58

标签: c# async-await

有没有办法让Task完成并在没有专用线程的情况下返回按键?

// Kernel callback, not a new thread in my process waiting for a keyboard event
var key = await KeyPress();

由于Console.ReadKey()是一个阻塞调用,并且仅使用线程等待用户输入。

2 个答案:

答案 0 :(得分:1)

您可以打开标准输入流,该输入流具有用于读取的异步操作:

using (var stream = Console.OpenStandardInput())
{
    var buffer = new byte[1];
    var bytesRead = await stream.ReadAsync(buffer, 0, 1);
    char c = (char)buffer[0];
    Console.WriteLine(c);
}

答案 1 :(得分:0)

  

就是这样,专门用于等待用户输入的线程听起来像是浪费   (不一定是一个大的,但它感觉它应该有一个   为此实施)。

对于需要用户输入的控制台应用程序,我不会担心这一点。

无论如何,通过使用一些底层的Win32 API,可能可以实现你所追求的目标。 ReadConsoleInput的文档说:

  

进程可以在其中一个等待中指定控制台输入缓冲区句柄   用于确定何时有未读控制台输入。当   输入缓冲区不为空,控制台输入缓冲区句柄的状态   发出信号。确定a中未读输入记录的数量   控制台的输入缓冲区,使用GetNumberOfConsoleInputEvents   功能。从没有控制台输入缓冲区读取输入记录   影响未读记录的数量,请使用PeekConsoleInput   功能。要丢弃控制台输入缓冲区中的所有未读记录,   使用FlushConsoleInputBuffer函数。

因此,理论上,您可以使用GetStdHandle返回的句柄并将其传递给 RegisterWaitForSingleObject。然后,您可以使用TaskCompletionSource将其转换为可等待的任务,例如正如here所述。

我在实践中没有证实这一点。它不应该阻止一个线程,但IMO,再次,这场比赛是不值得的。