7

我试图通过使用 FILE_FLAG_OVERLAPPED 标志打开 CONIN$ 来使用重叠 IO 从控制台读取输入。但是,当我使用它时,ReadFile 会阻塞,即使使用 OVERLAPPED 参数也是如此。

我读过一些帖子报告这是一个 Windows 7 错误。我正在使用 7,所以这是可能的。

这是我正在使用的代码:

// Create a console window
AllocConsole();
AttachConsole(GetProcessId(GetModuleHandle(NULL)));

HANDLE overlappedConsoleIn = CreateFile(L"CONIN$",
                              GENERIC_READ,
                              FILE_SHARE_READ,
                              NULL,
                              OPEN_EXISTING,
                              FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING,
                              NULL);

// Set up the console to work with stdio
FILE *consoleOut = _fdopen(_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT), "w");
FILE *consoleIn = _fdopen(_open_osfhandle((long)overlappedConsoleIn, _O_TEXT), "r");

*stdout = *consoleOut;
*stdin = *consoleIn;

setvbuf(consoleOut, NULL, _IONBF, 0);
setvbuf(consoleIn, NULL, _IONBF, 0);

std::ios::sync_with_stdio();

// Create a completion event
HANDLE inputEvent = CreateEvent(NULL, true, false, NULL);

BYTE inputBuffer[128];

OVERLAPPED overlappedData;
overlappedData.Offset = 0;
overlappedData.OffsetHigh = 0;
overlappedData.hEvent = inputEvent;

DWORD numBytesRead = 0;

// Asynchronously read from console
ReadFile(overlappedConsoleIn, inputBuffer, 128, &numBytesRead, &overlappedData);

while(true)
{
    if(WaitForSingleObject(inputEvent, 0) == WAIT_OBJECT_0)
    {
        std::cout << "input has been received" << std::endl;
    }
    std::cout << "doing something" << std::endl;
}
4

1 回答 1

6

当您打开CONIN$或忽略CONOUT$参数时dwFlagsAndAttributes(在CreateFile函数的文档中有关于如何打开控制台的完整描述)。如果您喜欢异步读取控制台,您可以将返回的句柄CreateFile直接传递给WaitForSingleObject函数,如果有任何控制台事件未决,则此句柄将发出信号,使用函数ReadConsoleInput读取未决事件。 是有关如何在 Windows 中使用控制台的完整文档。

于 2010-12-29T08:13:58.610 回答