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

C++实现异步(重叠)管道通信

主要思路是:

  1. 使用重叠 I/O(OVERLAPPED),避免阻塞 ConnectNamedPipe。
  2. 额外创建一个“停止事件”(hStopEvent),在线程中与管道事件一起 WaitForMultipleObjects,一旦收到停止事件就马上退出循环。
  3. 在主线程(或 OnNcDestroy)中 SetEvent(hStopEvent) 通知线程退出,然后再 CloseHandle 管道和事件。
// 假设这几个都是类成员或全局变量:
HANDLE hPipe = INVALID_HANDLE_VALUE;      // 管道句柄
HANDLE hStopEvent = NULL;                 // 停止事件
HANDLE hOvEvent   = NULL;                 // OVERLAPPED 事件
HANDLE hThread    = NULL;                 // 工作线程句柄bool OpenPipe(MsgHandleInterface* msgHandle)
{// 1. 创建停止事件(自动重置、初始未置位)hStopEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);if (!hStopEvent) return false;// 2. 创建 OVERLAPPED 专用事件hOvEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);if (!hOvEvent) {CloseHandle(hStopEvent);return false;}// 3. 创建命名管道,注意 FILE_FLAG_OVERLAPPEDLPCTSTR lpszPipename = TEXT(CMWAITMSGPIPENAME);hPipe = CreateNamedPipe(lpszPipename,PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,  // 重叠模式PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,1,BUFSIZE,BUFSIZE,0,NULL);if (hPipe == INVALID_HANDLE_VALUE) {CloseHandle(hOvEvent);CloseHandle(hStopEvent);return false;}// 4. 启动后台线程DWORD dwThreadId = 0;hThread = CreateThread(NULL,0,waitConnectThread,(LPVOID)msgHandle,    // 如果需要传递 msgHandle,可用结构体打包0,&dwThreadId);if (!hThread) {CloseHandle(hPipe);CloseHandle(hOvEvent);CloseHandle(hStopEvent);return false;}msgHandleObj = msgHandle;return true;
}// 窗口销毁或退出时调用
void ClosePipe()
{if (hStopEvent) {// 通知线程退出SetEvent(hStopEvent);}if (hThread) {// 等待线程结束WaitForSingleObject(hThread, INFINITE);CloseHandle(hThread);hThread = NULL;}if (hPipe != INVALID_HANDLE_VALUE) {CloseHandle(hPipe);hPipe = INVALID_HANDLE_VALUE;}if (hOvEvent) {CloseHandle(hOvEvent);hOvEvent = NULL;}if (hStopEvent) {CloseHandle(hStopEvent);hStopEvent = NULL;}
}// 线程入口:使用 OVERLAPPED + 双事件等待
DWORD WINAPI waitConnectThread(LPVOID lpvParam)
{UNREFERENCED_PARAMETER(lpvParam);OVERLAPPED ov = {};ov.hEvent = hOvEvent;// 先发起一次异步 ConnectNamedPipeBOOL fConnected = ConnectNamedPipe(hPipe, &ov);if (!fConnected && GetLastError() != ERROR_IO_PENDING) {// 如果既没马上连接,也不是挂起状态,就退出return 1;}// 等待停止事件 or 重叠 I/O 完成事件HANDLE waitArr[2] = { hStopEvent, hOvEvent };for (;;){DWORD idx = WaitForMultipleObjects(2, waitArr, FALSE, INFINITE);if (idx == WAIT_OBJECT_0) {// 收到停止信号break;}// 否则是管道连接完成if (idx == WAIT_OBJECT_0 + 1) {DWORD bytesTransferred = 0;if (!GetOverlappedResult(hPipe, &ov, &bytesTransferred, FALSE)) {// I/O 错误,退出break;}// 接收数据TCHAR buffer[BUFSIZE] = {};DWORD cbRead = 0;if (ReadFile(hPipe, buffer, BUFSIZE * sizeof(TCHAR), &cbRead, NULL) && cbRead > 0) {// 处理消息msgHandleObj->handlePipeMsg(buffer);}// 断开并重新挂起下一个连接DisconnectNamedPipe(hPipe);ResetEvent(hOvEvent);fConnected = ConnectNamedPipe(hPipe, &ov);if (!fConnected && GetLastError() != ERROR_IO_PENDING) {// 无法再次挂起连接,就退出break;}}else {// 其他错误break;}}return 0;
}
http://www.lryc.cn/news/572110.html

相关文章:

  • 【MySQL基础】MySQL内置函数全面解析:提升你的数据库操作效率
  • ③-1实现 FastAdmin 默认开启通用搜索功能的方法
  • 教学的新革命!大模型生成讲解,Manim 打造动画视频
  • 【MySQL】SQL基础
  • 50-Oracle awr报告生成-实操
  • 关于AB PLC的ethernet/IP 通信 c++搭建
  • 人机融合智能 | 人智交互语境下的设计新模态
  • Shell脚本应用及实战演练
  • SpringBoot电脑商城项目--收获地址列表
  • 数字华容道智力小游戏微信流量主小程序开源
  • 青少年编程与数学 01-012 通用应用软件简介 02 WPS Office办公软件
  • C#实现语音预处理:降噪、静音检测、自动增益
  • 【JavaEE】HTTPS协议
  • 【unitrix】 3.3 算术取负运算(neg.rs)
  • Kafka副本机制源码深度剖析:从数据同步到故障转移
  • craw14ai 框架的入门讲解和实战指南——基于Python的智能爬虫框架,集成AI(如NLP/OCR)实现自动化数据采集与处理
  • 3.1 Hector_mapping初体验
  • 前端如何通过 Blob 下载 Excel 文件
  • 容器运行时保护:用Falco构建云原生安全防线
  • CFG的前世今生
  • Docker 日志
  • 技术文章大纲:SpringBoot自动化部署实战
  • 《状压DP(01矩阵约束问题)》基础概念
  • 计算机网络:(五)信道复用技术,数字传输系统,宽带接入技术
  • 03 面试官考察与 CAP 有关的分布式理论
  • 开源ChatBI :深入解密 Spring AI Alibaba 的中文NL2SQL智能引擎
  • 基于RAGFlow构建Text2SQL的实战教程
  • 密室出逃消消乐小游戏微信流量主小程序开源
  • 如何将文件从安卓设备传输到电脑?
  • XMOS基于边缘AI+DSP+MCU+I/O智算芯片的音频解决方案矩阵引领行业创新潮流