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

Await keyboard event in a Console application

有没有办法在没有专用线程的情况下获得完成的 Task 和 returns 按键?

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

因为 Console.ReadKey() 是一个阻塞调用,只使用一个线程来等待用户输入。

您可以打开标准输入流,其中有读取的异步操作:

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);
}

that is the thing, a thread dedicated only to wait for user input sounds like a waste (not necessarily a big one, but it feels like it should have an implementation for this).

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

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

A process can specify a console input buffer handle in one of the wait functions to determine when there is unread console input. When the input buffer is not empty, the state of a console input buffer handle is signaled. To determine the number of unread input records in a console's input buffer, use the GetNumberOfConsoleInputEvents function. To read input records from a console input buffer without affecting the number of unread records, use the PeekConsoleInput function. To discard all unread records in a console's input buffer, use the FlushConsoleInputBuffer function.

因此,理论上,您可以使用 GetStdHandle 返回的句柄并将其传递给 RegisterWaitForSingleObject. Then you could convert it to an awaitable task using TaskCompletionSource, e.g. as described here

这个我没有在实践中验证过。它不应该阻塞线程,但 IMO,再一次,游戏不值得。