Win32 - 从标准输入读取超时 [英] Win32 - read from stdin with timeout

查看:40
本文介绍了Win32 - 从标准输入读取超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试做一些我认为应该很简单的事情:从标准输入进行阻塞读取,但如果没有数据可用,则在指定的时间间隔后超时.

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() 会很简单,但这在 Windows 中不起作用,因为 stdin 不是套接字.在不创建额外线程等的情况下,下一个最简单的选择是什么?

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 环境的 Visual C++.

I'm using visual C++ targeting a Win32 environment.

到目前为止我已经尝试过:

so far I have tried:

  1. 使用 select(如果输入不是套接字则不起作用)

  1. using select (doesn't work if the input is not a socket)

使用WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE)).- 雷米的第一个建议.如果标准输入是控制台,这似乎总是在您调用它时立即返回(其他人报告了同样的问题)

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 并执行 WaitForSingleObject(Remy 的第三个建议).在这种情况下,当输入来自控制台时,读取似乎总是阻塞 - 似乎 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.

目前我在想我唯一剩下的选择是创建一个线程,该线程将执行阻塞读取,然后发出一个事件信号,然后有另一个线程等待该事件超时.

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.

推荐答案

我不得不解决一个类似的问题.在 Windows 上,它不像 Linux 那样容易或明显.然而,这是可能的.诀窍是 Windows 将控制台事件放在控制台输入事件队列中.您必须过滤掉您不关心的事件,只处理您真正关心的事件(例如按键).

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).

进一步阅读:请参阅 Win32 控制台文档

以下是一些基于套接字和标准输入多路复用器的主要调试示例代码:

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
}

这篇关于Win32 - 从标准输入读取超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆