加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

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

发布时间:2020-12-14 02:51:04 所属栏目:Windows 来源:网络整理
导读:我有一个应用程序,它使用线程中的getline()从标准输入读取数据.我想从主线程关闭应用程序,而getline仍然阻止其他线程.怎么能实现这一目标? 我不想强迫用户必须按ctrl-Z来关闭stdin和应用程序. 到目前为止,我已尝试使用Windows 8.1 64bit,v120平台工具集上的
我有一个应用程序,它使用线程中的getline()从标准输入读取数据.我想从主线程关闭应用程序,而getline仍然阻止其他线程.怎么能实现这一目标?

我不想强迫用户必须按ctrl-Z来关闭stdin和应用程序.

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

> freopen stdin,但它被内部锁定阻止
>破坏线程,调用abort()
>将一个Eof,line end结束到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,'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;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读