問(wèn)題描述
我正在嘗試做一些我認(rèn)為應(yīng)該很簡(jiǎn)單的事情:從標(biāo)準(zhǔn)輸入進(jìn)行阻塞讀取,但如果沒(méi)有數(shù)據(jù)可用,則在指定的時(shí)間間隔后超時(shí).
I'm trying to do something which I think should be simple: do a blocking read from standard input, but timing out after a specified interval if no data is available.
在 Unix 世界中,使用 select()
會(huì)很簡(jiǎn)單,但這在 Windows 中不起作用,因?yàn)?stdin
不是套接字.在不創(chuàng)建額外線程等的情況下,下一個(gè)最簡(jiǎn)單的選擇是什么?
In the Unix world this would be simple with select()
but that doesn't work in Windows because stdin
isn't a socket. What's the next simplest option without creating extra threads etc?
我使用的是面向 Win32 環(huán)境的 Visual C++.
I'm using visual C++ targeting a Win32 environment.
到目前為止我已經(jīng)嘗試過(guò):
so far I have tried:
使用
select
(如果輸入不是套接字則不起作用)
using
select
(doesn't work if the input is not a socket)
使用WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE))
.- 雷米的第一個(gè)建議.如果標(biāo)準(zhǔn)輸入是控制臺(tái),這似乎總是在您調(diào)用它時(shí)立即返回(其他人報(bào)告了同樣的問(wèn)題)
using WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE))
. - Remy's first suggestion. This always seems to return immediately when you call it if the standard input is a console (others have reported the same problem)
使用重疊 IO 并執(zhí)行 WaitForSingleObject
(Remy 的第三個(gè)建議).在這種情況下,當(dāng)輸入來(lái)自控制臺(tái)時(shí),讀取似乎總是阻塞 - 似乎 stdin
不支持異步 I/O.
using overlapped IO and doing a WaitForSingleObject
(Remy's third suggestion). In this case the read always seems to block when the input is coming from a console - it seems that stdin
does not support asynchronous I/O.
目前我在想我唯一剩下的選擇是創(chuàng)建一個(gè)線程,該線程將執(zhí)行阻塞讀取,然后發(fā)出一個(gè)事件信號(hào),然后有另一個(gè)線程等待該事件超時(shí).
At the moment I'm thinking my only remaining option is to create a thread which will do a blocking read and then signal an event, and then have another thread which waits for the event with a timeout.
推薦答案
我不得不解決一個(gè)類(lèi)似的問(wèn)題.在 Windows 上,它不像 Linux 那樣容易或明顯.然而,這是可能的.訣竅是 Windows 將控制臺(tái)事件放在控制臺(tái)輸入事件隊(duì)列中.您必須過(guò)濾掉您不關(guān)心的事件,只處理您真正關(guān)心的事件(例如按鍵).
I had to solve a similar problem. On Windows it is not as easy or obvious as Linux. It is, however, possible. The trick is that Windows places console events in the console input event queue. You've got to filter out the events you don't care about and only process those events you do care about (like key presses).
進(jìn)一步閱讀:請(qǐng)參閱 Win32 控制臺(tái)文檔
以下是一些基于套接字和標(biāo)準(zhǔn)輸入多路復(fù)用器的主要調(diào)試示例代碼:
Here is some mostly-debugged sample code based on a socket and stdin multiplexer I was working on:
void ProcessStdin(void)
{
INPUT_RECORD record;
DWORD numRead;
if(!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &record, 1, &numRead)) {
// hmm handle this error somehow...
return;
}
if(record.EventType != KEY_EVENT) {
// don't care about other console events
return;
}
if(!record.Event.KeyEvent.bKeyDown) {
// really only care about keydown
return;
}
// if you're setup for ASCII, process this:
//record.Event.KeyEvent.uChar.AsciiChar
} // end ProcessStdin
int main(char argc, char* argv[])
{
HANDLE eventHandles[] = {
GetStdHandle(STD_INPUT_HANDLE)
// ... add more handles and/or sockets here
};
DWORD result = WSAWaitForMultipleEvents(sizeof(eventHandles)/sizeof(eventHandle[0]),
&eventHandles[0],
FALSE,
1000,
TRUE
);
switch(result) {
case WSA_WAIT_TIMEOUT: // no I/O going on right now
break;
case WSA_WAIT_EVENT_0 + 0: // stdin at array index 0
ProcessStdin();
break;
case WSA_WAIT_EVENT_0 + 1: // handle/socket at array index 1
break;
case WSA_WAIT_EVENT_0 + 2: // ... and so on
break;
default: // handle the other possible conditions
break;
} // end switch result
}
這篇關(guān)于Win32 - 從標(biāo)準(zhǔn)輸入讀取超時(shí)的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!