当前位置: 首页 > news >正文

Windows平台让标准输入(stdin)的阻塞立即返回

文章目录

  • 背景介绍
  • 代码示例
    • 版本1-基本命令处理
    • 版本2-多线程命令处理,不阻塞主函数
    • 版本3-即使没有用户输入,也能立即退出

背景介绍

  • 在开发命令行工具或控制台应用程序时,经常需要处理用户输入。常规做法是使用标准输入(stdin)来获取用户输入的数据。常见的有C语言的getchar()、C++的std::getline()以及Windows API的ReadFile()等函数这些操作通常是阻塞的:它们会挂起调用线程,直到有数据可读或者发生某种错误。
  • 然而,在某些应用场景中,可能需要在没有用户输入的情况下优雅地退出应用程序。例如,当系统需要进行紧急停止或转入其他任务时,如果输入线程因等待getchar()或std::getline()而阻塞,则无法立即响应。这种情况下,需要一种机制来使得阻塞在标准输入上的读取操作能够立即返回,从而允许程序继续执行或安全退出。
  • 接下来将介绍一种实现方案,旨在解决如何让标准输入的阻塞读取在必要时能够立即返回,以提高程序的响应能力和用户体验。

代码示例

版本1-基本命令处理

std::cout << "Enter commands ('read' or 'write'). Type 'exit' to quit:" << std::endl;
std::string command;
while (std::getline(std::cin, command)) {if (command == "exit") {break;  // 用户输入exit时退出循环}else if (command == "read") {std::cout << "Reading data..." << std::endl;}else if (command == "write") {std::cout << "Writing data..." << std::endl;}else {std::cout << "Unknown command. Please try 'read' or 'write'." << std::endl;}
}

版本2-多线程命令处理,不阻塞主函数

std::atomic_bool keep_running = true;  // 控制线程运行的原子标志
// 创建一个处理输入的线程
std::thread input_thread([&]() {std::cout << "Enter commands ('read' or 'write'). Type 'exit' to quit:" << std::endl;std::string command;// 循环读取命令,直到收到停止信号while (keep_running && std::getline(std::cin, command)) {if (command == "exit") {keep_running = false;  // 设置标志以终止循环break;}else if (command == "read") {std::cout << "Reading data..." << std::endl;}else if (command == "write") {std::cout << "Writing data..." << std::endl;}else {std::cout << "Unknown command. Please try 'read' or 'write'." << std::endl;}}});std::this_thread::sleep_for(std::chrono::seconds(10)); // 模拟等待一段时间或等待其他事件触发
keep_running = false;  // 通知线程停止
input_thread.join();  // 等待线程完成
  • 相较于版本1,版本2通过增加多线程处理避免了主函数的阻塞,并使用了原子标志位以便用户可以控制何时退出线程。但仍存在不足,由于输入线程依赖于 std::getline 的阻塞性质,它必须等到接收到用户输入后才能检查退出条件,因此程序的完全退出还需要依赖于用户输入,用户不输入任何内容,即使修改了标志位也无法让线程退出。

版本3-即使没有用户输入,也能立即退出

// 使用原子标志来控制线程是否应该继续运行。
std::atomic_bool keep_running = true;
// 获取标准输入的句柄。
HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE);// 创建一个处理输入的线程。
std::thread input_thread([&]() {std::cout << "Enter commands ('read' or 'write'). Type 'exit' to quit:" << std::endl;// 循环读取命令,直到收到停止信号。while (keep_running) {char buffer[256] = { 0 };DWORD bytes_read = 0;// 阻塞地从标准输入读取数据。if (ReadFile(stdin_handle, buffer, sizeof(buffer) - 1, &bytes_read, nullptr)) {buffer[bytes_read] = '\0'; // 确保字符串是以null终止的。std::string command(buffer);// 解析命令并执行相应操作。if (command == "exit") {keep_running = false; // 设置标志以终止循环。break;}else if (command == "read") {std::cout << "Reading data..." << std::endl;}else if (command == "write") {std::cout << "Writing data..." << std::endl;}else {std::cout << "Unknown command. Please try 'read' or 'write'." << std::endl;}}else {// 如果ReadFile失败,则输出失败消息。// 此处假设失败是因为主动取消ReadFile。std::cout << "ReadFile failure, because we want it exit." << std::endl;}}});// 主线程等待一段时间或等待其他事件触发。
std::this_thread::sleep_for(std::chrono::seconds(10));
// 通知输入线程停止。
keep_running = false;
// 取消所有挂起的I/O操作,以确保ReadFile可以退出。
CancelIoEx(stdin_handle, nullptr);
// 等待输入线程完成。
input_thread.join();
  • 在版本3中,引入了 CancelIoEx 函数,这个函数用于取消指定文件句柄上所有未完成的输入/输出(I/O)操作。调用 CancelIoEx 后,所有挂起的 I/O 操作会被取消,任何阻塞的 ReadFile 调用都将返回失败。这种失败的检测使我们能够在不等待用户输入的情况下让 ReadFile 从阻塞状态返回。随后,程序会检查循环条件(例如 keep_running 标志),从而实现立即终止。
  • 为什么不使用 OVERLAPPED 结构和 WaitForMultipleObjects:
    • 同步属性的标准输入:标准输入(stdin)的句柄在大多数情况下是同步的,并且不支持真正的异步操作。尽管可以采用 OVERLAPPED 结构来异步读取,实际上 ReadFile 仍然表现为阻塞调用,这意味着无法通过事件来判断其可读状态。
    • 简单性与需求满足:当前使用同步阻塞调用已足够满足我们的需求,即能够实现快速退出。这种同步调用方法在逻辑上更加简单直接。

相关文章:

Windows平台让标准输入(stdin)的阻塞立即返回

文章目录 背景介绍代码示例版本1-基本命令处理版本2-多线程命令处理&#xff0c;不阻塞主函数版本3-即使没有用户输入&#xff0c;也能立即退出 背景介绍 在开发命令行工具或控制台应用程序时&#xff0c;经常需要处理用户输入。常规做法是使用标准输入&#xff08;stdin&…...

Spring中的Aware接口

Spring中的Aware接口 Aware接口介绍 Aware是Spring中的接口&#xff0c;它的作用是可以让Bean获取到运行环境的相关信息。比如获取到上下文、Bean在容器中的名称等。 Spring中提供了很多Aware接口的子类&#xff0c;具体如下&#xff1a; 常用接口的作用如下&#xff1a; …...

FFmpeg滤镜完整列表

FFmpeg滤镜完整列表 滤镜名称 用途 acompressor 压缩音频信号,当输入信号超过某个预设阈值时&#xff0c;压缩器就会开始工作。该滤镜使音量大的部分变得不那么响亮&#xff0c;而音量小的部分相对变得响亮&#xff0c;这样就可以使整体听起来更加均衡&#xff0c;常用于音乐…...

深入探索Python基础:两个至关重要的函数

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、初学者的基石&#xff1a;print与input函数 二、类型转换&#xff1a;从字符串到浮点数…...

探索集合python(Set)的神秘面纱:它与字典有何不同?

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、集合&#xff08;Set&#xff09;与字典&#xff08;Dictionary&#xff09;的初识 1. …...

火山引擎“奇袭”阿里云

图片&#xff5c;电影《美国队长3》剧照 ©自象限原创 作者丨程心 编辑丨罗辑 大模型价格战&#xff0c;已经不是什么新闻。 从OpenAI发布GPT-4o&#xff0c;将API价格下调50%&#xff0c;并宣布面向普通用户免费开始&#xff0c;就标志着大模型的竞争从性能进入到了成本…...

牛客网刷题 | BC94 反向输出一个四位数

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 将一个四位数&…...

记一次MySQL执行修改语句超时问题

异常问题 原因分析 这个问题发生在开发环境&#xff0c;怀疑是提交事务时终止项目运行&#xff0c;没有提交该事务&#xff0c;造成死锁 调试该事务时时间太长&#xff0c;为什么说有这个原因呢&#xff0c;因为通过查找日志显示 The client was disconnected by the server …...

linux fork()函数调用原理

在Linux中,fork函数用于创建一个新的进程,该进程是调用进程的子进程。fork函数的实现涉及用户态和内核态之间的交互。下面我将详细说明fork函数在代码流程中的原理和用户态与内核态的交互过程。 用户态调用fork函数: 用户程序调用fork函数,该函数是libc库提供的一个封装函数…...

【电控笔记5.9】编码器脉冲计算速度MT法

总结 编码器的脉冲计算速度可以使用多种方法,其中一种常用的方法是“MT法” (Measuring Time Method),即测量时间法。该方法通过测量编码器脉冲间的时间来计算速度。这种方法在高精度速度测量中非常有效,特别是在速度较低时。 MT法计算速度的基本原理 MT法的基本原理是通过…...

go-zero 实战(4)

中间件 在 userapi 项目中引入中间件。go项目中的中间可以处理请求之前和之后的逻辑。 1. 在 userapi/internal目录先创建 middlewares目录&#xff0c;并创建 user.go文件 package middlewaresimport ("github.com/zeromicro/go-zero/core/logx""net/http&q…...

go语言泛型Generic最佳实践 --- slices包

在go的内置包slices中&#xff0c; 所有的函数函数都使用了泛型&#xff0c; 各种各样的泛型&#xff0c; 可以说这个包绝对是go语言泛型学习的最佳实践之一&#xff01; 来&#xff0c;先来瞄一眼&#xff0c;看看这个slices包里面的函数原型定义&#xff1a; func BinarySe…...

【神经网络结构可视化】使用 Visualkeras 可视化 Keras / TensorFlow 神经网络结构

文章目录 Visualkeras介绍下载安装代码示例1、导入必要的库2、创建VGG16神经网络模型3、可视化神经网络结构4、完整代码5、使用教程 可视化自己创建的神经网络结构1、导入要的库2、创建自己的神经网络模型3、可视化神经网络结构图4、完整代码 Visualkeras介绍 Visualkeras是一…...

nvm安装nodejs/npm/nvm笔记

1 安装nvm, 指定路径nvm路径&#xff1a; D:\Program_Files\nvm\nvm指定路径nodejs 路径&#xff1a; D:\Program_Files\nvm\nodejs 2 进入nvm安装路径找到settings.xml文件,追加2行&#xff0c;设置镜像 node_mirror: https://npmmirror.com/mirrors/node/ npm_mirror: ht…...

微信小程序源码-基于Java后端的小区租拼车管理信息系统毕业设计(附源码+演示录像+LW)

大家好&#xff01;我是程序员一帆&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;微信小程序毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设…...

嵌入式进阶——LED呼吸灯(PWM)

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 PWM基础概念STC8H芯片PWMA应用PWM配置详解占空比 PWM基础概念 PWM全称是脉宽调制&#xff08;Pulse Width Modulation&#xff09…...

一文读懂:http免费升级https

背景&#xff1a; 随着现在全民网络安全意识的日益提升&#xff0c;各个网站需要实现的https数量也随之提升&#xff0c;那么如何将原本网站的http访问方式升级为https呢&#xff1f; 该内容为如何免费将网站的http访问升级为https访问 论https的加密逻辑&#xff1a; 步骤 …...

算法刷题笔记 高精度除法(C++实现)

文章目录 题目描述求解思路实现代码 题目描述 给定两个非负整数&#xff08;不含前导0&#xff09;A&#xff0c;B&#xff0c;请你计算 A/B 的商和余数。 输入格式 共两行&#xff0c;第一行包含整数A&#xff0c;第二行包含整数B。 输出格式 共两行&#xff0c;第一行输…...

按月爬取天气数据可视化展示

从天气网分析,可以查询每个月的天气情况,这里按照url规则,传入年月,获取数据,最后进行可视化展示,最终效果: 下面是获取过程: 第一步: import requestsdef get_weather(month):url = f"https://lishi.tianqi.com/nanning/{month}.html"response = reques…...

VMware安装Ubuntu系统(超详细)

一.Ubuntu官网下载镜像 Ubuntu官网&#xff1a;Enterprise Open Source and Linux | Ubuntu 二.安装Ubuntu系统 选择文件->创建虚拟机新建虚拟机&#xff08;ControlN&#xff09;&#xff0c;这里直接选择典型即可 选择稍后安装系统 选择linux Ubuntu 64位 填写虚拟机名称…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…...