通过进程协作显示图像-C#

前言

如果一个软件比较复杂或者某些情况下需要拆解,可以考试将软件分解成两个或多个进程,但常规的消息传递又不能完全够用,使用消息+共享内存,实现图像传递,当然性能这个方面我并没有测试,仅是一种解决思路吧。

一、效果展示

1、调用方

2、被调用方

二、实现代码

1、主调打开调用进程

主要是为了拿到Handle,为发送消息函数提供操作句柄。

2、创建共享内存

        /// <summary>/// 创建共享内存/// </summary>/// <returns>0=创建成功;1=创建共享体失败;2=打开失败;3=印射失败; 4=共享内存命名错误</returns>public int CreateMemory(){if (MemSize <= 0) MemSize = 0x00800000;if (ShareName.Length > 0){//创建内存共享体(INVALID_HANDLE_VALUE)m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)MemSize, ShareName);if (m_hSharedMemoryFile == IntPtr.Zero){m_bAlreadyExist = false;m_bInit = false;MemPtr = IntPtr.Zero;return 1; //创建共享体失败}else{if (GetLastError() == ERROR_ALREADY_EXISTS) //已经创建{m_bAlreadyExist = true;CloseHandle(m_hSharedMemoryFile);m_hSharedMemoryFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, ShareName);if (m_hSharedMemoryFile == null){MemPtr = IntPtr.Zero;return 2;//打开共享内存失败}}else                                         //新创建{m_bAlreadyExist = false;}}//创建内存映射m_rwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, (uint)MemSize);if (m_rwData == IntPtr.Zero){m_bInit = false;CloseHandle(m_hSharedMemoryFile);MemPtr = IntPtr.Zero;return 3; //创建内存映射失败}else{m_bInit = true;MemPtr = m_rwData;}}else{return 4; //参数错误}return 0;     //创建成功}

3、读取本地图像并写图像数据到共享内存中

 MyAlgoProcessNet.HImage hImage = new MyAlgoProcessNet.HImage(fileName);IntPtr prt = hImage.GetImagePointer1(out string type, out imageData.Widht, out imageData.Height);imageData.dataLength = imageData.Widht * imageData.Height;byte[] datas = new byte[imageData.dataLength];Marshal.Copy(prt, datas, 0, imageData.dataLength);int pos = Marshal.SizeOf(imageData);share1.WriteToMemory(imageData);//写共享内存if (share1.WriteBytes(datas, pos + 1) == 0){WriteMsg("share1写入共享内存成功");}else{WriteMsg("share1写入共享内存失败!!");}public int WriteBytes(byte[] datas, int pos = -1){if (IntPtr.Zero == MemPtr){return -1;}if (pos == -1){Marshal.Copy(datas, 0, MemPtr, datas.Length);}else{IntPtr offPtr = IntPtr.Add(MemPtr, pos);Marshal.Copy(datas, 0, offPtr, datas.Length);}return 0;}

4、通知读取数据

private void SendMsg2(string msg)
{// 获取目标进程句柄IntPtr hWnd = process.MainWindowHandle;// 封装消息byte[] sarr = System.Text.Encoding.Default.GetBytes(msg);int len = sarr.Length;COPYDATASTRUCT cds2;cds2.dwData = (IntPtr)0;cds2.cbData = len + 1;cds2.lpData = msg;// 发送消息WriteMsg(msg + " Start");SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ref cds2);WriteMsg(msg + " End");
}

5、被调用方关联消息处理函数

        protected override void OnSourceInitialized(EventArgs e){base.OnSourceInitialized(e);HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;if (hwndSource != null){IntPtr handle = hwndSource.Handle;hwndSource.AddHook(new HwndSourceHook(WndProc));}}

6、被调用方处理图像数据

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled){if (msg == WM_COPYDATA){WriteInfo(1, "WndProc Start");COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam,typeof(COPYDATASTRUCT)); // 接收封装的消息string rece = cds.lpData; // 获取消息内容// 自定义行为//  Console.WriteLine(rece);if (rece == "Read"){Task.Run(() =>{//读共享内存// datastruct = (MemoryClass)shareMemory.ReadFromMemory(typeof(MemoryClass));// WriteInfo(1, $"读取数据:{datastruct.bianliang1},{datastruct.bianliang2},{datastruct.bianliang3}");imageData = (ImageData)shareMemory.ReadFromMemory(typeof(ImageData));int ShareSize = Marshal.SizeOf(imageData);byte[] datas = shareMemory.ReadByteFromMemory(imageData.dataLength, ShareSize + 1);HImage hImage = new HImage();using (PinnedObject pinnedObject = new PinnedObject(datas)){hImage.GenImage1("byte", imageData.Widht, imageData.Height, pinnedObject.Pointer);}// hImage.GenImage1(imageData.DataType, imageData.Widht, imageData.Height, imageData.dataPrt);ImgControl.HalconWindow.AttachBackgroundToWindow(hImage);WriteInfo(1, "图像处理完成");});}// Thread.Sleep(2000);WriteInfo(2, rece);if (rece.Equals("Close")){this.Close();}}return hwnd;}

7、共享内存操作

  internal class ShareMemory{[DllImport("user32.dll", CharSet = CharSet.Auto)]public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]public static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]public static extern bool CloseHandle(IntPtr handle);[DllImport("kernel32", EntryPoint = "GetLastError")]public static extern int GetLastError();private const int INVALID_HANDLE_VALUE = -1;private const int ERROR_ALREADY_EXISTS = 0xB7;//183private const int PAGE_READWRITE = 0x04;private const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004;private const int FILE_MAP_READ = 0x0004;private const int FILE_MAP_WRITE = 0x0002;private IntPtr m_hSharedMemoryFile = IntPtr.Zero;private IntPtr m_rwData = IntPtr.Zero;private bool m_bAlreadyExist = false;private bool m_bInit = false;private string ShareName { get; set; } //共享内存的名字private long MemSize { get; set; }//共享内存大小private IntPtr MemPtr { get; set; }//共享内存印射地址/// <summary>/// 共享内存初始化/// </summary>/// <param name="MemName">共享内存名字</param>/// <param name="MemSize">共享内存大小</param>public ShareMemory(string MemName, long Size){ShareName = MemName;MemSize = Size;MemPtr = IntPtr.Zero;m_bInit = false;m_bAlreadyExist = false;m_rwData = IntPtr.Zero;m_hSharedMemoryFile = IntPtr.Zero;}~ShareMemory(){ShareMemoryClose();}/// <summary>/// 创建共享内存/// </summary>/// <returns>0=创建成功;1=创建共享体失败;2=打开失败;3=印射失败; 4=共享内存命名错误</returns>public int CreateMemory(){if (MemSize <= 0) MemSize = 0x00800000;if (ShareName.Length > 0){//创建内存共享体(INVALID_HANDLE_VALUE)m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)MemSize, ShareName);if (m_hSharedMemoryFile == IntPtr.Zero){m_bAlreadyExist = false;m_bInit = false;MemPtr = IntPtr.Zero;return 1; //创建共享体失败}else{if (GetLastError() == ERROR_ALREADY_EXISTS) //已经创建{m_bAlreadyExist = true;CloseHandle(m_hSharedMemoryFile);m_hSharedMemoryFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, ShareName);if (m_hSharedMemoryFile == null){MemPtr = IntPtr.Zero;return 2;//打开共享内存失败}}else                                         //新创建{m_bAlreadyExist = false;}}//创建内存映射m_rwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, (uint)MemSize);if (m_rwData == IntPtr.Zero){m_bInit = false;CloseHandle(m_hSharedMemoryFile);MemPtr = IntPtr.Zero;return 3; //创建内存映射失败}else{m_bInit = true;MemPtr = m_rwData;}}else{return 4; //参数错误}return 0;     //创建成功}public byte[] ReadByteFromMemory(int dataLength, int pos = -1){if (IntPtr.Zero == MemPtr){return new byte[0];}byte[] datas = new byte[dataLength];if (pos == -1){Marshal.Copy(MemPtr, datas, 0, dataLength);}else{IntPtr offPtr = IntPtr.Add(MemPtr, pos);Marshal.Copy(offPtr, datas, 0, dataLength);}return datas;}/// <summary>/// 读取共享内存并返回到类/// </summary>/// <param name="type">读取的类型</param>/// <returns>读取的数据</returns>public Object ReadFromMemory(Type type){if (IntPtr.Zero == MemPtr){return null;}Object obj = Marshal.PtrToStructure(MemPtr, type);return obj;}/// <summary>/// 读取类并写入共享内存/// </summary>/// <param name="obj">需要读取的类(结构体)</param>/// <returns>返回0表示写入成功,返回-1表示写入失败</returns>public int WriteToMemory(Object obj){if (IntPtr.Zero == MemPtr){return -1;}Marshal.StructureToPtr(obj, MemPtr, false);return 0;}/// <summary>/// 关闭共享内存(解除印射,关闭句柄)/// </summary>public void ShareMemoryClose(){if (m_bInit){UnmapViewOfFile(m_rwData);CloseHandle(m_hSharedMemoryFile);m_bInit = false;}}/// <summary>/// 获取共享内存印射地址/// </summary>/// <returns></returns>public IntPtr GetPtr(){return MemPtr;}/// <summary>/// 获取文件句柄/// </summary>/// <returns></returns>public IntPtr GetFileMapPtr(){return m_hSharedMemoryFile;}/// <summary>/// 获取共享内存大小/// </summary>/// <returns></returns>public long GetSize(){return MemSize;}/// <summary>/// 获取共享内存名字/// </summary>/// <returns></returns>public string GetName(){return ShareName;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/387693.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tekion 选择 ClickHouse Cloud 提升应用性能和指标监控

本文字数&#xff1a;4187&#xff1b;估计阅读时间&#xff1a;11 分钟 作者&#xff1a;ClickHouse team 本文在公众号【ClickHouseInc】首发 Tekion 由前 Tesla CIO Jay Vijayan 于 2016 年创立&#xff0c;利用大数据、人工智能和物联网等技术&#xff0c;为其汽车客户解决…

如何通过 CloudCanal 实现从 Kafka 到 AutoMQ 的数据迁移

01 引言 随着大数据技术的飞速发展&#xff0c;Apache Kafka 作为一种高吞吐量、低延迟的分布式消息系统&#xff0c;已经成为企业实时数据处理的核心组件。然而&#xff0c;随着业务的扩展和技术的发展&#xff0c;企业面临着不断增加的存储成本和运维复杂性问题。为了更好地…

【数据中台】大数据管理平台建设方案(原件资料)

建设大数据管理中台&#xff0c;按照统一的数据规范和标准体系&#xff0c;构建统一数据采集&#xfe63;治理&#xfe63;共享标准、统一技术开发体系、统一接口 API &#xff0c;实现数据采集、平台治理&#xff0c;业务应用三层解耦&#xff0c;并按照统一标准格式提供高效的…

electron安装及快速创建

electron安装及快速创建 electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 详细内容见官网&#xff1a;https://www.electronjs.org/zh/docs/latest/。 今天来记录下练习中的安装过程和hello world的创建。 创建项目文件夹&#xff0c;并执行npm 初始化命…

ubuntu安装tar安装 nginx最新版本

一、需要先安装依赖 apt install gcc libpcre3 libpcre3-dev zlib1g zlib1g-dev openssl libssl-dev 二、上传安装包 并解压 下载地址 nginx news tar xvf nginx-1.25.2.tar.gz 进入nginx cd nginx-1.25.2 三、编译 ./configure --prefix=/usr/local/nginx --with-htt…

Dolphinscheduler 3.2.1bug记录

问题1&#xff1a;分页只展示首页 解决方案&#xff1a; [Bug][API] list paging missing totalpage by Gallardot Pull Request #15619 apache/dolphinscheduler GitHub 问题2:Hive 数据源连接失败 解决方案&#xff1a;修改源码&#xff1a;HiveDataSourceProcessor.cla…

《深度RAG系列》 LLM 为什么选择了RAG

2023年是AIGC&#xff08;Artificial Intelligence Generated Content&#xff09;元年&#xff0c;这一年见证了人工智能生成内容领域的巨大飞跃&#xff0c;特别是大模型的爆发&#xff0c;它们在自然语言处理、图像生成、音频处理等多个领域展现出了惊人的能力。 这些预训练…

数据结构和算法入门

1.了解数据结构和算法 1.1 二分查找 二分查找&#xff08;Binary Search&#xff09;是一种在有序数组中查找特定元素的搜索算法。它的基本思想是将数组分成两半&#xff0c;然后比较目标值与中间元素的大小关系&#xff0c;从而确定应该在左半部分还是右半部分继续查找。这个…

花8000元去培训机构学习网络安全值得吗,学成后就业前景如何?

我就是从培训机构学的网络安全&#xff0c;线下五六个月&#xff0c;当时学费不到一万&#xff0c;目前已成功入行。所以&#xff0c;只要你下决心要入这一行&#xff0c;过程中能好好学&#xff0c;那这8000就花得值~ 因为只要学得好&#xff0c;工作两个多月就能赚回学费&am…

浅谈取样器之OS进程取样器

浅谈取样器之OS进程取样器 JMeter 的 OS 进程取样器&#xff08;OSProcess Sampler&#xff09;允许用户在 JMeter 测试计划中直接执行操作系统命令或脚本。这一功能对于需要集成系统级操作到性能测试场景中尤为有用&#xff0c;比如运行数据库备份脚本、调用系统维护命令或执…

存储引擎MyISAM和InnoDB

存储引擎&#xff1a;创建、查询、更新、删除 innoDB&#xff1a;64T、支持事物、不支持全文索引、支持缓存、支持外键、行级锁定 MyISAM&#xff1a;256T、不支持事物、支持全文索引、插入和查询速度快 memory&#xff1a;内存、不支持事物、不支持全文索引&#xff0c;临时…

不得不安利的程序员开发神器,太赞了!!

作为一名程序员&#xff0c;你是否常常为繁琐的后端服务而感到头疼&#xff1f;是否希望有一种工具可以帮你简化开发流程&#xff0c;让你专注于创意和功能开发&#xff1f;今天&#xff0c;我要向大家隆重推荐一款绝佳的开发神器——MemFire Cloud。它专为懒人开发者准备&…

KVM高级功能部署

KVM&#xff08;Kernel-based Virtual Machine&#xff09;是一个在Linux内核中实现的全虚拟化解决方案。除了基本的虚拟化功能外&#xff0c;KVM还提供了许多高级功能&#xff0c;以增强其性能、安全性和灵活性。以下是一些KVM的高级功能&#xff1a; 硬件加速&#xff1a; In…

基于Deap遗传算法在全量可转债上做因子挖掘(附python代码及全量因子数据)

原创文章第604篇&#xff0c;专注“AI量化投资、世界运行的规律、个人成长与财富自由"。 在4.x的时候&#xff0c;咱们分享过deap遗传算法挖掘因子的代码和数据&#xff0c;今天我们来升级到5.x中。 源码发布Quantlab4.2&#xff0c;Deap因子挖掘|gplearn做不到的咱们也…

全新微软语音合成网页版源码,短视频影视解说配音网页版系统-仿真人语音

源码介绍 最新微软语音合成网页版源码&#xff0c;可以用来给影视解说和短视频配音。它是TTS文本转语言&#xff0c;API接口和PHP源码。 这个微软语音合成接口的源码&#xff0c;超级简单&#xff0c;就几个文件搞定。用的是官方的API&#xff0c;试过了&#xff0c;合成速度…

Datawhale AI夏令营 AI+逻辑推理 Task2总结

Datawhale AI夏令营 AI逻辑推理 Task2总结 一、大语言模型解题方案介绍 1.1 大模型推理介绍 ​ 推理是建立在训练完成的基础上&#xff0c;将训练好的模型应用于新的、未见过的数据&#xff0c;模型利用先前学到的规律进行预测、分类和生成新内容&#xff0c;使得AI在实际应…

力扣SQL50 换座位

Problem: 626. 换座位 &#x1f468;‍&#x1f3eb; 参考题解 Code SELECT(CASEWHEN MOD(id, 2) ! 0 AND counts ! id THEN id 1WHEN MOD(id, 2) ! 0 AND counts id THEN idELSE id - 1END) AS id,student FROMseat,(SELECTCOUNT(*) AS countsFROMseat) AS seat_counts O…

C语言实现三子棋

通过一段时间的学习&#xff0c;我们已经能够较为熟练地使用分支语句&#xff0c;循环语句&#xff0c;创建函数&#xff0c;创建数组&#xff0c;创建随机数等。之前我们做过一个扫雷游戏&#xff0c;今天让我们再尝试创作一个三子棋游戏吧~ 一、三子棋游戏的思路 三子棋的游…

AI Agent调研--7种Agent框架对比!盘点国内一站式Agent搭建平台,一文说清差别!大家都在用Agent做什么?

代理&#xff08;Agent&#xff09;乃一种智能实体&#xff0c;具备自主环境感知与决策行动能力&#xff0c;旨在达成既定目标。作为个人或组织之数字化替身&#xff0c;AI代理执行特定任务与交易&#xff0c;其核心价值在于简化工作流程&#xff0c;削减繁复性&#xff0c;并有…

IoTDB 入门教程 实战篇④——C#示例(开源)

文章目录 一、前文二、新建C#项目三、NuGet安装四、示例源码五、查询数据六、参考 一、前文 IoTDB入门教程——导读 本文详细阐述了如何通过一个C#项目成功连接到IoTDB时序数据库&#xff0c;进而展示了如何向该数据库高效地写入数据以及执行精确的数据查询操作。 此示例旨在为…