四种线程间的通信(笔记)

不加锁的线程间通信 烽驿2009开源实时通信平台 源码获取:svn checkout http://fy2009.googlecode.com/svn/trunk/ fy2009-read-only  在线程间共享内存时需要加锁应该算是多线程编程的常识了,因此,这个标题显得有些颠覆性。但请注意这里说的是共享内存,而标题说的是通信,两者并不是一回事,仔细分析,后者在内涵上应该包括前者,即通信才是目的,而 阅读详情
有四种方法

1.剪贴板
  a.创建个ClipBoard的对话框应用程序
,加两EditBox和两个Button发送接收。
  b.具体代码:
    发送端代码:
if(OpenClipboard())
{
  CString str;
  HANDLE hClip;
  char *pBuf;
  EmptyClipboard();
  GetDlgItemText(IDC_EDIT_SEND,str);
  hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1);
  pBuf=(char*)GlobalLock(hClip);将句柄转换为指针!
  strcpy(pBuf,str);
  GlobalUnlock(hClip);
  SetClipboardData(CF_TEXT,hClip);
  CloseClipboard();
}
     接收端代码:
if(OpenClipboard())
{
  if(IsClipboardFormatAvailable(CF_TEXT))
  {
   HANDLE hClip;
   char *pBuf;
   hClip=GetClipboardData(CF_TEXT);
   pBuf=(char*)GlobalLock(hClip);
   GlobalUnlock(hClip);
   SetDlgItemText(IDC_EDIT_RECV,pBuf);
   CloseClipboard();
  }
}
2.匿名管道:只能在父子进程之间进行通信
  a.先建一个Parent的单文档应用程序,增加“创建管道”“读取数据”“写入数据”三个菜单
  b.增加成员变量HANDLE类型的hRead,hWrite,初始化变量,并在析构函数中释放句柄
  c.响应菜单代码:
void CParentView::OnPipeCreate() 菜单“创建管道”代码
{
// TOD Add your command handler code here
SECURITY_ATTRIBUTES sa;
sa.bInheritHandle=TRUE;
sa.lpSecurityDescriptor=NULL;
sa.nLength=sizeof(SECURITY_ATTRIBUTES);
if(!CreatePipe(&hRead,&hWrite,&sa,0))
{
  MessageBox("创建匿名管道失败!");
  return;
}
STARTUPINFO sui;
PROCESS_INFORMATION pi;
ZeroMemory(&sui,sizeof(STARTUPINFO));将数据清0!
sui.cb=sizeof(STARTUPINFO);
sui.dwFlags=STARTF_USESTDHANDLES;
sui.hStdInput=hRead;
sui.hStdOutput=hWrite;
sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);

if(!CreateProcess("../Child/Debug/Child.exe",NULL,NULL,NULL,
   TRUE,0,NULL,NULL,&sui,&pi))创建子进程
{
  CloseHandle(hRead);
  CloseHandle(hWrite);关闭句柄,将内核对象的使用计数减少1,这样当操作系统发现内核对象的使用计数为0时,将清除内核对象。
  hRead=NULL;
  hWrite=NULL;
  MessageBox("创建子进程失败!");
  return;
}
else
{
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);
}
}
void CParentView::OnPipeRead() 菜单“读取数据”代码
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
  MessageBox("读取数据失败!");
  return;
}
MessageBox(buf);
}
void CParentView::OnPipeWrite() 菜单“写入数据”代码
{
// TOD Add your command handler code here
char buf[]="http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
  MessageBox("写入数据失败!");
  return;
}
}
     d.再建一个Child的单文档,在View中增加两个成员hRead和hWrite.在OnInitialUpdate()中得到句柄的值。
void CChildView::OnInitialUpdate()
{
CView::OnInitialUpdate();

// TOD Add your specialized code here and/or call the base class
hRead=GetStdHandle(STD_INPUT_HANDLE);注意这句代码!
hWrite=GetStdHandle(STD_OUTPUT_HANDLE);
}
     e. 加菜单“读取数据”“写入数据”其代码如下:
void CChildView::OnPipeRead()
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hRead,buf,100,&dwRead,NULL))
{
  MessageBox("读取数据失败!");
  return;
}
MessageBox(buf);
}
void CChildView::OnPipeWrite()
{
// TOD Add your command handler code here
char buf[]="
匿名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hWrite,buf,strlen(buf)+1,&dwWrite,NULL))
{
  MessageBox("写入数据失败!");
  return;
}
}
3. 命名管道:还可以跨网络通信,服务器只能在win2000和NT下运行!而客户端可以在95下运行。关键函数CreateNamedPipe
  a.先建一个NamedPipeSRV单文档应用程序,加菜单“创建管道”“读取数据”“写入数据”
  b.在View中增加Handle变量hPipe,注意在析构函数中释放它!
  c.响应菜单,创建命名管道
void CNamedPipeSrvView::OnPipeCreate()
{
// TOD Add your command handler code here
hPipe=CreateNamedPipe("//./pipe/MyPipe",
  PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
  0,1,1024,1024,0,NULL);
if(INVALID_HANDLE_VALUE==hPipe)
{
  MessageBox("创建命名管道失败!");
  hPipe=NULL;
  return;
}
HANDLE hEvent;
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(!hEvent)
{
  MessageBox("创建事件对象失败!");
  CloseHandle(hPipe);
  hPipe=NULL;
  return;
}
OVERLAPPED ovlap;
ZeroMemory(&ovlap,sizeof(OVERLAPPED));
ovlap.hEvent=hEvent;
if(!ConnectNamedPipe(hPipe,&ovlap))
{
  if(ERROR_IO_PENDING!=GetLastError())
  {
   MessageBox("等待客户端连接失败!");
   CloseHandle(hPipe);
   CloseHandle(hEvent);
   hPipe=NULL;
   return;
  }
}
if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE))
{
  MessageBox("等待对象失败!");
  CloseHandle(hPipe);
  CloseHandle(hEvent);
  hPipe=NULL;
  return;
}
CloseHandle(hEvent);
}
void CNamedPipeSrvView::OnPipeRead()
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
  MessageBox("
读取数据失败!");
  return;
}
MessageBox(buf);
}
void CNamedPipeSrvView::OnPipeWrite()
{
// TOD Add your command handler code here
char buf[]="http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
  MessageBox("
写入数据失败!");
  return;
}
}
      d. 再建一个NamedPipeCLT单文档工程,加菜单“连接管道”“读取数据”“写入数据”,当然别忘记成员变量hPipe的定义和初始化
      e.响应菜单代码
void CNamedPipeCltView::OnPipeConnect() 连接管道
{
// TOD Add your command handler code here
if(!WaitNamedPipe("//./pipe/MyPipe",NMPWAIT_WAIT_FOREVER))
{
  MessageBox("当前没有可利用的命名管道实例!");
  return;
}
hPipe=CreateFile("//./pipe/MyPipe",GENERIC_READ | GENERIC_WRITE,
  0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hPipe)
{
  MessageBox("打开命名管道失败!");
  hPipe=NULL;
  return;
}
}
void CNamedPipeCltView::OnPipeRead() 读取数据
{
// TOD Add your command handler code here
char buf[100];
DWORD dwRead;
if(!ReadFile(hPipe,buf,100,&dwRead,NULL))
{
  MessageBox("读取数据失败!");
  return;
}
MessageBox(buf);
}
void CNamedPipeCltView::OnPipeWrite() 写入数据
{
// TOD Add your command handler code here
char buf[]="命名管道测试程序";
DWORD dwWrite;
if(!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
{
  MessageBox("写入数据失败!");
  return;
}
}
4. 邮槽,使用时应将消息长度限制在424字节以下,关键函数CreateMailSlot()
  a.先建一个MailSlotSRV工程,加菜单“接收数据”
  b.消息响应代码:
void CMailslotSrvView::OnMailslotRecv() 菜单“接收数据”的代码
{
// TOD Add your command handler code here
HANDLE hMailslot;
hMailslot=CreateMailslot("//./mailslot/MyMailslot",0,
  MAILSLOT_WAIT_FOREVER,NULL);
if(INVALID_HANDLE_VALUE==hMailslot)
{
  MessageBox("创建油槽失败!");
  return;
}
char buf[100];
DWORD dwRead;
if(!ReadFile(hMailslot,buf,100,&dwRead,NULL))
{
  MessageBox("读取数据失败!");
  CloseHandle(hMailslot);
  return;
}
MessageBox(buf);
CloseHandle(hMailslot);
}
    c.加工程MailSlotCLT,加菜单“发送数据”
    d.加消息响应,添加代码,客户端也比较简单。
void CMailslotCltView::OnMailslotSend() 菜单“发送数据”的代码
{
// TOD Add your command handler code here
HANDLE hMailslot;
hMailslot=CreateFile("//./mailslot/MyMailslot",GENERIC_WRITE,
  FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE==hMailslot)
{
  MessageBox("打开油槽失败!");
  return;
}
char buf[]="http://www.sunxin.org";
DWORD dwWrite;
if(!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))
{
  MessageBox("写入数据失败!");
  CloseHandle(hMailslot);
  return;
}
CloseHandle(hMailslot);
}
5. 以上4种方法各有优缺点:剪贴板比较简单。邮槽是基于广播的,可以一对多发送。但只能一个发送,一个接收,要想同时发送接收,须写两次代码。
命名管道和邮槽可以进行网络通信。
 
QProcess进程间通信.rar QProcess 实现父子进程间的双向通信。子进程获取父进程write发送的数据。windows下测试通过 立即下载

相关推荐

MailSlot简单封装和使用

邮槽的简单封装,简要介绍,客户端和服务端简单demo,vs2010可直接编译运行。操作简单,邮槽的简单封装,简要介绍,客户端和服务端简单demo,vs2010可直接编译运行。操作简单,

PyQT 多进程

在PyQt中,图形化界面(GUI)是运行在主线程中的,而多进程是在独立的进程中执行的。默认情况下,多进程之间是无法直接共享图形化界面的。然而,有几种方法可以在多进程中与PyQt的图形化界面进行通信:使用进程间通信(Inter-Process Communication,IPC)机制,如管道(Pipe)、共享内存(Shared Memory)或消息队列(Message Queue)。你可以在主线程中创建一个IPC对象,然后将其传递给子进程,子进程可以使用该对象与主线程进行通信。

llf000000的博客 2800

Uniapp H5端SEO优化全攻略:提升搜索引擎排名与流量

在移动互联网时代,H5页面因其跨平台、低成本、易传播的特性,成为许多企业的首选。Uniapp作为一款优秀的前端跨端开发框架,能够快速开发H5、小程序、App等多端应用。然而,由于Uniapp默认采用SPA(单页应用)架构,H5端在SEO(搜索引擎优化)方面存在一定劣势,如爬虫难以抓取动态内容、页面标题和描述不易优化等。 本文将系统性地介绍Uniapp H5端的SEO优化方案,涵盖基础优化、SPA优化策略、内容优化、技术优化、外部优化及监测分析,帮助开发者提升网站在搜索引擎中的排名,获取更多自然流量。

vvilkin的学习备忘 1973

python进程间通信

目录概述消息队列管道共享内存服务器进程 概述 python的进程间通信主要有以下几种方式:消息队列(Queue)、管道(Pipe)、共享内存(Value,Array)、代理(Manager), 以上分为两个类型, 进程间交互对象:消息队列(Queue)、管道(Pipe) 进程间同步:共享内存(Value,Array)、代理(Manager) 消息队列 消息队列常用于单向交互,消息队列操作简单,用于单向交互最方便。 示例 from multiprocessing import Process, Queue

chise_ 1671

常见消息队列:ActiveMQ、RabbitMQ、RocketMQ、Kafka的区别总结

常见消息队列:ActiveMQ、RabbitMQ、RocketMQ、Kafka的区别。

qq_30713721的博客 3471

2 利用ITK实现多帧Dicom读取,VTK实现数据显示

vtk中也有dicom读写类,但是只能完成单帧DICOM数据读取,这对于实际应用是非常不利的。而ITK可以实现dicom多帧读取,通常情况ITK与VTK也会结合使用(ITK处理,VTK显示),所以就一起学习下吧!

buerbuhuitou的博客 1565

17.2匿名管道

17.2匿名管道 17.2.1基础知识 //匿名管道是一个未命名的、单向管道,通常用在一个父进程和一个子进程之间传输数据。匿名管道只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。为创建匿名管道,需要调用CreatePipe函数: BOOL CreatePipe( PHANDLE hReadPipe, // 返回管道读取的句柄 PHANDLE hWritePipe, // 接收管道写入的句柄 LPSECURITY_ATTRIBU

qq_42148307的博客 640

新手如何结合pbootCMS和宝塔面板快速构建网站

摘要: 新手可通过pbootCMS(轻量CMS)和宝塔面板(可视化工具)快速搭建网站,无需命令行。步骤包括:1) 准备服务器(Linux/CentOS7.x)和域名;2) 安装宝塔面板并配置LNMP环境(PHP7.4+MySQL5.7);3) 创建网站目录,上传并解压pbootCMS源码,设置文件权限;4) 运行安装向导,填写数据库信息和管理员账号;5) 测试前台/后台功能,优化性能并绑定域名。全程约30-60分钟,宝塔简化运维,pbootCMS便于内容管理,适合零基础用户。注意定期更新和备份以保障安全。

qinzhenyan的博客 1643

进程间通信之匿名管道

关键步骤 【1】创建管道(一定是主进程创建) 【2】创建子进程 【3】两个进程都有读写匿名管道的功能 主进程的主要处理函数(MFC)void CParentView::OnPipeCreate() { // TODO: Add your command handler code here SECURITY_ATTRIBUTES sa; sa.bInheritHandle=T

蜕变的博客 560

手把手教你使用ConvNeXt训练自己数据集和推理,ConvNeXt模型训练(CVPR 2022),一个能挑战 Vision Transformer 的卷积神经网络,含完整代码和数据集

手把手教你使用ConvNeXt训练自己数据集和推理,ConvNeXt模型训练(CVPR 2022),一个能挑战 Vision Transformer 的卷积神经网络,含完整代码和数据集

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1454

ardupilot开发 --- MavLink 篇

ardupilot开发 --- MavLink 篇

记录老板的每次pua,分享领导每天的毒鸡汤... 4252

孙鑫MFC第十七讲 进程间通信的方法:剪切板,管道,匿名管道,邮槽

有四种方法 1.剪贴板  a.创建个ClipBoard的对话框应用程序,加两EditBox和两个Button发送接收。  b.具体代码:    发送端代码:  if(OpenClipboard())  {  CString str;  HANDLE hClip;  char *pBuf;  EmptyClipboard();  GetDlgItemText(IDC_EDIT_

lvjun93的专栏 2867

火灾图像检测识别:cnn卷积神经网络 Adaboost 支持向量机 随机森林 决策树 完整代码数据

火灾图像检测识别:cnn卷积神经网络 Adaboost 支持向量机 随机森林 决策树 完整代码数据

864

四种线程间的通信(笔记) - yuyunliuhen的专栏 - 优快云Blog

导读:   有四种方法   1.剪贴板   a.创建个ClipBoard的对话框应用程序,加两EditBox和两个Button发送接收。   b.具体代码:   发送端代码:   if(OpenClipboard())   {   CString str;   HANDLE hClip;   char *pBuf;   EmptyClipboard();   GetDlgItemText(

菠菜的专栏 771

基于机器学习的网络入侵检测系统设计与实现

本文设计并实现了一个基于机器学习的网络入侵检测系统,采用随机森林模型结合KMM算法优化,使用CICIDS2017数据集进行训练。系统包含完整的数据预处理流程、特征工程、模型调优和远程部署方案。实验结果表明,该系统能有效识别多种网络攻击类型,在检测准确率和误报率方面表现优异。研究为网络安全防护提供了新的技术思路和实用工具,具有重要的应用价值。

huanghm88的专栏 319

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

线程间通信的几种实现方式

线程间通信的几种实现方式 首先,要短信线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析: 题目:有两个线程A、B,A线程向一个集合里面依次添加元素"abc"字符串,一共添加十次,当添加到第五次的时候,希望B线程能够收到A线程的通知,然后B线程执行相关的业务操作。 方式一:使用 volatile 关键字 基于 volatile...

InterfaceJ的博客 18万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

线程间的通信

线程间的通信 1.线程之间的通信简介 一般而言,在一个应用程序中(即进程),一个线程往往不是孤立存在的,常常需要和其它线程通信,以执行特定的任务。如主线程和次线程,次线程与次线程,工作线程和用户界面线程等。这样,线程与线程间必定有一个信息传递的渠道。这种线程间的通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的。线程间的通信涉及到4个问题: (1) 线程间如何传递信息 (2)  线程

cbNotes的专栏:不积硅步,无以至千里;不积小流,无以成江海! 5万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

鸿蒙中的并发线程间通信、线程间通信对象

并发线程间通信,线程间通信对象、Worker、TaskPool

2301_79624024的博客 1680

线程间通信方式

一般而言,在一个应用程序(即进程)中,一个线程往往不是孤立存在的,常常需要和其它线程通信,以执行特定的任务。如主线程和次线程,次线程与次线程,工作线程和用户界面线程等。这样,线程与线程间必定有一个信息传递的渠道。这种线程间的通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的。线程间的通信涉及到4个问题:a.线程间如何传递信息;b.线程之间如何同步,以使一个线程的活动不会破坏另一个线程的活动,以保证计算结果的正确合理;c.当线程间具有依赖关系时,如何调度多个线程的处理顺序;

Bossking321的博客 3505

Android线程间通信

Android线程间通信 前言:内容主要从android线程间通信方式进行入手,首先分析了线程间通信的几种方式,再深入分析线程间通信的机制,主要分析工作线程与工作线程间通信,因为主线程和工作线程间通信网上已经很多例子了。 目录 Android线程间通信 一、Android线程间通信的四种实现方式 1.Handler进行线程通信==>消息机制 2.runOnUiThread 3.View.post(Runnable r) 4.AsyncTask 二、线程间通信机制 一、Andr.

居家小男的博客 1683

线程间通信

线程间通信

m0_61787196的博客 1774

python中的线程间通信

前面学习了线程的一些基本知识如与进程的区别,线程的组成,线程如何创建等,接下来继续线程的学习。

瑞瑞的博客 3976

线程间通信是什么

线程间通信是什么

weixin_45428910的博客 858

java干货 线程间通信

java干货 线程间通信

qq_51305563的博客 1419

android线程间通信的几种方法_Android线程间通信机制

讲解Handler机制的博文很多,我也看了很多,但说实话,在我对Handler几乎不怎么了解的情况下,每一篇文章我都没太看懂,看完之后脑子里还是充满了疑问。究其原因,是因为几乎每一篇文章一上来就开始深入Handler源码,使得在一些宏观的问题上还是充满疑问,如果你从来没接触过Handler,对一些基础的问题还充满疑问,那深入源码去探究根源肯定会有些吃力。下面,我就从一个初学者思考的角度,来讲一讲H...

weixin_36316291的博客 2046
上一篇: 三种线程间的同步
下一篇: Spring学习笔记1
Image_Graphics
博客等级 码龄20年 18粉丝 52原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值