开发者社区> 杰克.陈> 正文

c#读写共享内存操作函数封装

简介: 原文 c#读写共享内存操作函数封装   c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂。         现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方面则是做个备份吧。
+关注继续查看

原文 c#读写共享内存操作函数封装

  c#共享内存操作相对c++共享内存操作来说原理是一样,但是c#会显得有点复杂。

        现把昨天封装的读写共享内存封装的函数记录下来,一方面希望给需要这块的有点帮助,另一方面则是做个备份吧。

 

[csharp] view plaincopy
  1. /// <summary>  
  2.         /// 写共享内存  
  3.         /// </summary>  
  4.         /// <param name="structSize">需要映射的文件的字节数量</param>  
  5.         /// <param name="obj">映射对象(简单类型、结构体等)</param>  
  6.         /// <param name="fileName">文件映射对象的名称</param>  
  7.         /// <param name="windowName">发送消息的窗口句柄</param>  
  8.         /// <param name="Msg">发送消息</param>  
  9.         /// <returns></returns>  
  10.         public static int WriteToMemory(uint structSize, Object obj, string fileName, string windowName, uint Msg)  
  11.         {  
  12.             IntPtr hShareMemoryHandle = IntPtr.Zero;  
  13.             IntPtr hVoid = IntPtr.Zero;  
  14.   
  15.             //判断参数的合法性  
  16.             if (structSize > 0 && fileName.Length > 0)  
  17.             {  
  18.                 hShareMemoryHandle = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)structSize, fileName);  
  19.                 if (hShareMemoryHandle == IntPtr.Zero)  
  20.                 {  
  21.                     //创建共享内存失败,记log  
  22.                     MessageBox.Show("创建共享内存失败"+publicInfo.GetLastError().ToString());  
  23.                     return -2;  
  24.                 }  
  25.                 else  
  26.                 {  
  27.                     if (ERROR_ALREADY_EXISTS == GetLastError())  
  28.                     {  
  29.                         //共享内存已经存在,记log  
  30.                         MessageBox.Show("共享内存已经存在");  
  31.                         return -3;  
  32.                     }  
  33.                 }  
  34.                 hVoid = MapViewOfFile(hShareMemoryHandle, FILE_MAP_WRITE, 0, 0, structSize);  
  35.                 if (hVoid == IntPtr.Zero)  
  36.                 {  
  37.                     CloseHandle(hShareMemoryHandle);  
  38.                     //文件映射失败,记log  
  39.                     MessageBox.Show("文件映射失败");  
  40.                     return -4;  
  41.                 }  
  42.                 Marshal.StructureToPtr(obj, hVoid, false);  
  43.                 //发送消息,通知接收  
  44.                 IntPtr handle = FindWindow(null, windowName.Trim());  
  45.                 if (handle == IntPtr.Zero)  
  46.                 {  
  47.                     //查找窗口失败,记log  
  48.                     MessageBox.Show("查找窗口失败");  
  49.                     return -5;  
  50.                 }  
  51.                 else  
  52.                 {  
  53.                     if (PostMessage(handle, (uint)Msg, 0, 0))  
  54.                     {  
  55.                         //发送消息成功  
  56.                         //MessageBox.Show("写共享内存,通知发送消息成功");  
  57.                     }  
  58.                 }  
  59.             }  
  60.             else  
  61.             {  
  62.                 //参数不合法,记log  
  63.                 MessageBox.Show("共享内存已经存在");  
  64.                 return -1;  
  65.             }  
  66.             return 0;  
  67.         }  

  写共享内存函数并没有什么需要说明,完全按照:

 

创建共享内存文件(CreateFileMapping)---》映射文件视图到调用进程的地址空间(MapViewOfFile)---》写数据到共享内存(Marshal.StructureToPtr)----》发送消息通知需要读共享内存的窗口(PostMessage)

 

[csharp] view plaincopy
  1. /// <summary>  
  2.         /// 读共享内存  
  3.         /// </summary>  
  4.         /// <param name="structSize">需要映射的文件的字节数量</param>  
  5.         /// <param name="type">类型</param>  
  6.         /// <param name="fileName">文件映射对象的名称</param>  
  7.         /// <returns>返回读到的映射对象</returns>  
  8.         public static Object ReadFromMemory(uint structSize, Type type, string fileName)  
  9.         {  
  10.   
  11.             IntPtr hMappingHandle = IntPtr.Zero;  
  12.             IntPtr hVoid = IntPtr.Zero;  
  13.   
  14.             hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);  
  15.             if (hMappingHandle == IntPtr.Zero)  
  16.             {  
  17.                 //打开共享内存失败,记log  
  18.                 MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());  
  19.                 return null;  
  20.             }  
  21.             hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);  
  22.             if (hVoid == IntPtr.Zero)  
  23.             {  
  24.                 //文件映射失败,记log  
  25.                 MessageBox.Show("文件映射失败——读共享内存");  
  26.                 return null;  
  27.             }  
  28.   
  29.             Object obj = Marshal.PtrToStructure(hVoid, type);  
  30.   
  31.             if (hVoid != IntPtr.Zero)  
  32.             {  
  33.                 UnmapViewOfFile(hVoid);  
  34.                 hVoid = IntPtr.Zero;  
  35.             }  
  36.             if (hMappingHandle != IntPtr.Zero)  
  37.             {  
  38.                 CloseHandle(hMappingHandle);  
  39.                 hMappingHandle = IntPtr.Zero;  
  40.             }  
  41.             return obj;  
  42.         }  

 

         读共享内存,上边代码是一种方式,这里是传入一个Type类型,这样就确保可以传入任何类型。当读到共享内存的数据时,采用

         public static object PtrToStructure(IntPtr ptr, Type structureType);

        函数,把非托管指针(共享内存获得的指针)转换为需要转换的Type类型的对象。如果需要的话,可以通过显示类型转换转换为需要的类型(例子继续看)。

       

[csharp] view plaincopy
  1. /// <summary>  
  2.         /// 读共享内存  
  3.         /// </summary>  
  4.         /// <param name="structSize">需要映射的文件的字节数量</param>  
  5.         /// <param name="type">类型</param>  
  6.         /// <param name="fileName">文件映射对象的名称</param>  
  7.         /// <returns>返回读到的映射字节数据</returns>  
  8.         public static byte[] ReadFromMemory(uint structSize, Type type, string fileName)  
  9.         {  
  10.   
  11.             IntPtr hMappingHandle = IntPtr.Zero;  
  12.             IntPtr hVoid = IntPtr.Zero;  
  13.   
  14.             hMappingHandle = OpenFileMapping((uint)FILE_MAP_READ, false, fileName);  
  15.             if (hMappingHandle == IntPtr.Zero)  
  16.             {  
  17.                 //打开共享内存失败,记log  
  18.                 MessageBox.Show("打开共享内存失败:" + publicInfo.GetLastError().ToString());  
  19.                 return null;  
  20.             }  
  21.             hVoid = MapViewOfFile(hMappingHandle, FILE_MAP_READ, 0, 0, structSize);  
  22.             if (hVoid == IntPtr.Zero)  
  23.             {  
  24.                 //文件映射失败,记log  
  25.                 MessageBox.Show("文件映射失败——读共享内存");  
  26.                 return null;  
  27.             }  
  28.   
  29.             //Object obj = Marshal.PtrToStructure(hVoid, type);  
  30.             byte[] bytes = new byte[structSize];  
  31.             Marshal.Copy(hVoid, bytes, 0, bytes.Length);  
  32.   
  33.             if (hVoid != IntPtr.Zero)  
  34.             {  
  35.                 UnmapViewOfFile(hVoid);  
  36.                 hVoid = IntPtr.Zero;  
  37.             }  
  38.             if (hMappingHandle != IntPtr.Zero)  
  39.             {  
  40.                 CloseHandle(hMappingHandle);  
  41.                 hMappingHandle = IntPtr.Zero;  
  42.             }  
  43.             return bytes;  
  44.         }  

        此代码和第一个读共享内存不同的是,采用byte[]读需要的共享内存。使用托管类中的Copy来转换指针。

 

 

[csharp] view plaincopy
  1. byte[] bytes = new byte[structSize];  
  2. arshal.Copy(hVoid, bytes, 0, bytes.Length);  

 

      调用简单例子部分代码如下:

注:passiveInfo是NotifyInfo结构体对象。

      写共享内存:

 

[csharp] view plaincopy
  1. int iRet = publicInfo.WriteToMemory((uint)Marshal.SizeOf(passiveInfo),(Object)passiveInfo, "memName","FormMsg",(uint)publicInfo.WM_NOTIFY);  

 

     读共享内存:

第一种情况调用:

 

[csharp] view plaincopy
  1. passiveInfo = (NotifyPassiveInfo)publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), typeof(NotifyPassiveInfo), publicInfo.SN_PASSIVEINFO);  

      第二种情况调用:

 

[csharp] view plaincopy
  1. byte[] bytes = publicInfo.ReadFromMemory((uint)Marshal.SizeOf(passiveInfo), "memName");  
  2. passiveInfo = (NotifyInfo)BytesToStuct(bytes, typeof(NotifyInfo));  

 

 

      希望对你有帮助。

     转载请标注:http://blog.csdn.net/richerg85

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【原】修改shm,oracle11g需要扩大共享内存
作者:david_zhang@sh 【转载时请以超链接形式标明文章】 链接:http://www.cnblogs.com/david-zhang-index/archive/2012/04/26/2472087.
883 0
MySQL 基础---存储过程和函数操作
存储过程和函数就是实现经过编译并存储在数据库中的一段sql语句集合。函数必须有返回值,而存储过程则没有。存储过程的参数类型远远多于函数参数类型。 存储过程和函数的优点: 存储过程和函数允许标准组件式编程,提高了SQL语句的重用性、共享性和可移植性。
1028 0
Java基础-22总结登录注册IO版,数据操作流,内存操作流,打印流,标准输入输出流,转换流,随机访问流,合并流,序列化流,Properties
你需要的是什么,直接评论留言。 获取更多资源加微信公众号“Java帮帮” (是公众号,不是微信好友哦) 还有“Java帮帮”今日头条号,技术文章与新闻,每日更新,欢迎阅读 学习交流请加Java帮帮交流QQ群553841695 分享是一种美德,分享更快乐! 1:登录注册IO版本案例(掌握) 要求,对着写一遍。 cn.i
1794 0
Juc11_Java内存模型之JMM、八大原子操作、三大特性、读写过程、happens-before(二)
③. JVMM规范下,三大特性 ①. 可见性 ②. 原子性 ③. 有序性 ④. JVMM规范下,多线程对变量的读写过程
18 0
+关注
杰克.陈
一个安静的程序猿~
10427
文章
2
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载