windows - 在 stdin 在 Windows 上阻塞时退出应用程序

标签 windows multithreading c++11 stdin msvc12

我有一个应用程序,它在线程中使用 getline() 从标准输入读取数据。我想从主线程关闭应用程序,而 getline 仍然阻塞另一个线程。如何实现?

我不想强制用户必须按 ctrl-Z 来关闭标准输入和应用程序。

到目前为止,我已经尝试在 Windows 8.1 64 位 v120 平台工具集上使用我的编译器设置 (RuntimeLibrary=/MT):

  • freopen stdin,但它被内部锁阻止
  • 销毁调用 abort() 的线程
  • 将 Eof、行尾返回到 std::cin,这也被阻塞了

* 更新 *

  • detach() 不起作用,exit() 被锁阻塞
  • winapi TerminatThread() 调用 abort()
  • winapi CloseHandle(GetStdHandle(STD_INPUT_HANDLE)) 挂起
  • 调用 TerminateProcess() - 有效,但我想优雅地退出

* 更新 2:解决方案 *

  • WriteConsoleInput() 可以使 std::getline() 从阻塞读取中返回。这适用于任何 msvc 运行时库。有关工作解决方案的代码,请参阅已接受的答案。

显示问题的示例代码:

#include <iostream>
#include <thread>
#include <string>
#include <chrono>

int main(int argc, char *argv[])
{
    bool stop = false;
    std::thread *t = new std::thread([&]{
        std::string line;
        while (!stop && std::getline(std::cin, line, '\n')) {
            std::cout << line;
        }
    });

    std::this_thread::sleep_for(std::chrono::seconds(1));

    stop = true;
    // how to stop thread or make getline to return here?

    return 0;
}

最佳答案

writeConsoleInput()可以让std::getline从阻塞读取中返回,所以即使使用/MT编译器选项也可以解决问题。

#include <Windows.h>

#include <iostream>
#include <thread>
#include <string>
#include <chrono>
#include <atomic>

int main(int argc, char *argv[])
{
    std::atomic_bool stop;

    stop = false;

    std::thread t([&]{
        std::string line;
        while (!stop.load() && std::getline(std::cin, line, '\n')) {
            std::cout << line;
        }
    });


    std::this_thread::sleep_for(std::chrono::seconds(1));

    stop = true;

    DWORD dwTmp;
    INPUT_RECORD ir[2];
    ir[0].EventType = KEY_EVENT;
    ir[0].Event.KeyEvent.bKeyDown = TRUE;
    ir[0].Event.KeyEvent.dwControlKeyState = 0;
    ir[0].Event.KeyEvent.uChar.UnicodeChar = VK_RETURN;
    ir[0].Event.KeyEvent.wRepeatCount = 1;
    ir[0].Event.KeyEvent.wVirtualKeyCode = VK_RETURN;
    ir[0].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC);
    ir[1] = ir[0];
    ir[1].Event.KeyEvent.bKeyDown = FALSE;
    WriteConsoleInput(GetStdHandle(STD_INPUT_HANDLE), ir, 2, &dwTmp);

    t.join();

    return 0;
}

关于windows - 在 stdin 在 Windows 上阻塞时退出应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31657775/

相关文章:

java - 如何在 Windows 上使用另一个用户帐户创建新进程?

c++ - 在C++中收到输入时如何停止执行异步功能

c - 如何判断两个线程是否访问了同一 block 内存?

c++ - POSIX - pthread_kill()?

c++ - 令人惊讶的是, vector <char> 的自定义分配器效率低下

c++ - 在 (C++-AMP) 中处理异构 vector

c++ - 函数 to_string() 未使用 g++ mingw --w64 5.3.0 解析

windows - PE 文件 - 缺少什么?

windows - WiX 在重大升级后删除 Windows 服务

windows - 批处理命令如何为 set/p 制作列表