Windows平臺中用WaitForSingleObject API,採用阻塞模型偵聽標準文件輸入事件
爲命令行C/C++編程時,通常我們使用getch/getche或C++的cin來等待用戶輸入。在Linux編程中,工程中更常用的做法是通過select阻塞/偵聽模型同時偵聽標準輸入和socket句柄等,這樣可以很方便地根據用戶鍵入的命令及時處理不同的任務。那麼,在Windows Console編程中是否也能夠實現同樣的功能呢?答案是肯定的,但是用到的是WaitForSingleObject/WaitForMultiObject API。
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include <string>
#include <iostream>
using namespace std;
enum {
CMD_ERROR = -1,
CMD_NONE,
CMD_QUIT,
};
static int Reading(HANDLE hStdIn);
int _tmain(int argc, _TCHAR* argv[])
{
//獲取標準輸入句柄
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
while (1) {
//阻塞
DWORD dwWaitResult = WaitForSingleObject(hStdIn, 5000);
try {
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
// 標準輸入有鍵入動作,讀鍵入的命令
switch(Reading(hStdIn)) {
case CMD_QUIT:
case CMD_ERROR:
Sleep(500);
return 0;
}
FlushConsoleInputBuffer(hStdIn);
break;
case WAIT_ABANDONED:
break;
}
}
catch(...)
{
// Handle error.
}
}
return 0;
}
static int Reading(HANDLE hStdIn)
{
DWORD cbRead;
BOOL fResult;
HANDLE hEvent;
OVERLAPPED ov;
char buffer[512];
hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("EtEvent"));
if( NULL == hEvent ) {
printf("Create overlap event failed !!! \n");
return CMD_ERROR;
}
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = hEvent;
while (hEvent) // retrieve all messages
{
memset(buffer, 0, sizeof(buffer));
fResult = ReadFile(hStdIn,
buffer,
sizeof(buffer) - 1,
&cbRead,
&ov);
if (!fResult)
{
printf("ReadFile failed with %d.\n", GetLastError());
CloseHandle(hEvent);
return CMD_NONE;
}
for (DWORD i = 0; i < cbRead; i++) {
switch (buffer[i + 0]) {
case 'Q':
CloseHandle(hEvent);
return CMD_QUIT;
default:
break;
}
}
}
CloseHandle(hEvent);
return CMD_ERROR;
}
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include <string>
#include <iostream>
using namespace std;
enum {
CMD_ERROR = -1,
CMD_NONE,
CMD_QUIT,
};
static int Reading(HANDLE hStdIn);
int _tmain(int argc, _TCHAR* argv[])
{
//獲取標準輸入句柄
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
while (1) {
//阻塞
DWORD dwWaitResult = WaitForSingleObject(hStdIn, 5000);
try {
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
// 標準輸入有鍵入動作,讀鍵入的命令
switch(Reading(hStdIn)) {
case CMD_QUIT:
case CMD_ERROR:
Sleep(500);
return 0;
}
FlushConsoleInputBuffer(hStdIn);
break;
case WAIT_ABANDONED:
break;
}
}
catch(...)
{
// Handle error.
}
}
return 0;
}
static int Reading(HANDLE hStdIn)
{
DWORD cbRead;
BOOL fResult;
HANDLE hEvent;
OVERLAPPED ov;
char buffer[512];
hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("EtEvent"));
if( NULL == hEvent ) {
printf("Create overlap event failed !!! \n");
return CMD_ERROR;
}
ov.Offset = 0;
ov.OffsetHigh = 0;
ov.hEvent = hEvent;
while (hEvent) // retrieve all messages
{
memset(buffer, 0, sizeof(buffer));
fResult = ReadFile(hStdIn,
buffer,
sizeof(buffer) - 1,
&cbRead,
&ov);
if (!fResult)
{
printf("ReadFile failed with %d.\n", GetLastError());
CloseHandle(hEvent);
return CMD_NONE;
}
for (DWORD i = 0; i < cbRead; i++) {
switch (buffer[i + 0]) {
case 'Q':
CloseHandle(hEvent);
return CMD_QUIT;
default:
break;
}
}
}
CloseHandle(hEvent);
return CMD_ERROR;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.