我有一个应用程序,它在线程中使用 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/