C# 进程间通信(共享内存)
进程间通信的方式有很多,常用的方式有:
1.共享内存(内存映射文件,共享内存DLL)。
2.命名管道和匿名管道。
3.发送消息
本文是记录共享内存的方式进行进程间通信,首先要建立一个进程间共享的内存地址,创建好共享内存地址后,一个进程向地址中写入数据,另外的进程从地址中读取数据。
在数据的读写的过程中要进行进程间的同步。
进程间数据同步可以有以下的方式
1. 互斥量Mutex
2. 信号量Semaphore
3. 事件Event
本文中进程间的同步采用 信号量Semaphore的方式同步思想类似于操作系统中生产者和消费者问题的处理方式。
在A进程中创建共享内存,并开启一个线程用来读取B进程向共享内存中写入的数据,定义两个信号量进行读写互斥同步
A进程中的程序代码
using System;
using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Runtime.InteropServices;using System.Threading;using System.Diagnostics;namespace AppOne{ public partial class AppOneMain : Form { const int INVALID_HANDLE_VALUE = -; const int PAGE_READWRITE = 0x04; [DllImport("User32.dll")] private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow); [DllImport("User32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); //共享内存 [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")] private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile, UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes, // UInt32 flProtect,//DWORD flProtect UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh, UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow, string lpName//LPCTSTR lpName ); [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")] private static extern IntPtr OpenFileMapping( UInt32 dwDesiredAccess,//DWORD dwDesiredAccess, int bInheritHandle,//BOOL bInheritHandle, string lpName//LPCTSTR lpName ); const int FILE_MAP_ALL_ACCESS = 0x0002; const int FILE_MAP_WRITE = 0x0002; [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")] private static extern IntPtr MapViewOfFile( IntPtr hFileMappingObject,//HANDLE hFileMappingObject, UInt32 dwDesiredAccess,//DWORD dwDesiredAccess UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh, UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow, UInt32 dwNumberOfBytesToMap//SIZE_T dwNumberOfBytesToMap ); [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")] private static extern int UnmapViewOfFile(IntPtr lpBaseAddress); [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")] private static extern int CloseHandle(IntPtr hObject); private Semaphore m_Write; //可写的信号 private Semaphore m_Read; //可读的信号 private IntPtr handle; //文件句柄 private IntPtr addr; //共享内存地址 uint mapLength; //共享内存长 //线程用来读取数据 Thread threadRed; public AppOneMain() { InitializeComponent(); init(); } ///<summary>/// 初始化共享内存数据 创建一个共享内存 ///</summary>privatevoid init() { m_Write = new Semaphore(, , "WriteMap");//开始的时候有一个可以写 m_Read = new Semaphore(, , "ReadMap");//没有数据可读 mapLength = ; IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE); handle = CreateFileMapping(hFile, , PAGE_READWRITE, , mapLength, "shareMemory"); addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, , , ); //handle = OpenFileMapping(0x0002, 0, "shareMemory"); //addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0); threadRed = new Thread(new ThreadStart(ThreadReceive)); threadRed.Start(); } /// <summary> /// 线程启动从共享内存中获取数据信息 /// </summary> private void ThreadReceive() { myDelegate myI = new myDelegate(changeTxt); while (true) { try { //m_Write = Semaphore.OpenExisting("WriteMap"); //m_Read = Semaphore.OpenExisting("ReadMap"); //handle = OpenFileMapping(FILE_MAP_WRITE, 0, "shareMemory"); //读取共享内存中的数据: //是否有数据写过来 m_Read.WaitOne(); //IntPtr m_Sender = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0); byte[] byteStr = new byte[]; byteCopy(byteStr, addr); string str = Encoding.Default.GetString(byteStr, , byteStr.Length); /////调用数据处理方法 处理读取到的数据 m_Write.Release(); } catch (WaitHandleCannotBeOpenedException) { continue; //Thread.Sleep(0); } } } //不安全的代码在项目生成的选项中选中允许不安全代码 static unsafe void byteCopy(byte[] dst, IntPtr src) { fixed (byte* pDst = dst) { byte* pdst = pDst; byte* psrc = (byte*)src; while ((*pdst++ = *psrc++) != '\0') ; } } }}
B进程向共享内存中写入的数据
using System;
using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Runtime.InteropServices;using System.Threading;namespace AppTwo{ public partial class AppTwoMain : Form { const int INVALID_HANDLE_VALUE = -; const int PAGE_READWRITE = 0x04; //共享内存 [DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")] private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile, UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes, // UInt32 flProtect,//DWORD flProtect UInt32 dwMaximumSizeHigh,//DWORD dwMaximumSizeHigh, UInt32 dwMaximumSizeLow,//DWORD dwMaximumSizeLow, string lpName//LPCTSTR lpName ); [DllImport("Kernel32.dll", EntryPoint = "OpenFileMapping")] private static extern IntPtr OpenFileMapping( UInt32 dwDesiredAccess,//DWORD dwDesiredAccess, int bInheritHandle,//BOOL bInheritHandle, string lpName//LPCTSTR lpName ); const int FILE_MAP_ALL_ACCESS = 0x0002; const int FILE_MAP_WRITE = 0x0002; [DllImport("Kernel32.dll", EntryPoint = "MapViewOfFile")] private static extern IntPtr MapViewOfFile( IntPtr hFileMappingObject,//HANDLE hFileMappingObject, UInt32 dwDesiredAccess,//DWORD dwDesiredAccess UInt32 dwFileOffsetHight,//DWORD dwFileOffsetHigh, UInt32 dwFileOffsetLow,//DWORD dwFileOffsetLow, UInt32 dwNumberOfBytesToMap//SIZE_T dwNumberOfBytesToMap ); [DllImport("Kernel32.dll", EntryPoint = "UnmapViewOfFile")] private static extern int UnmapViewOfFile(IntPtr lpBaseAddress); [DllImport("Kernel32.dll", EntryPoint = "CloseHandle")] private static extern int CloseHandle(IntPtr hObject); private Semaphore m_Write; //可写的信号 private Semaphore m_Read; //可读的信号 private IntPtr handle; //文件句柄 private IntPtr addr; //共享内存地址 uint mapLength; //共享内存长 Thread threadRed; public AppTwoMain() { InitializeComponent(); //threadRed = new Thread(new ThreadStart(init)); //threadRed.Start(); mapLength = ; } private void button1_Click(object sender, EventArgs e) { try { m_Write = Semaphore.OpenExisting("WriteMap"); m_Read = Semaphore.OpenExisting("ReadMap"); handle = OpenFileMapping(FILE_MAP_WRITE, , "shareMemory"); addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, , , ); m_Write.WaitOne(); byte[] sendStr = Encoding.Default.GetBytes(textBox1.Text.ToString() + '\0'); //如果要是超长的话,应另外处理,最好是分配足够的内存 if (sendStr.Length < mapLength) Copy(sendStr, addr); m_Read.Release(); } catch (WaitHandleCannotBeOpenedException) { MessageBox.Show("不存在系统信号量!"); return; } } static unsafe void Copy(byte[] byteSrc, IntPtr dst) { fixed (byte* pSrc = byteSrc) { byte* pDst = (byte*)dst; byte* psrc = pSrc; for (int i = ; i < byteSrc.Length; i++) { *pDst = *psrc; pDst++; psrc++; } } } }}
C# 进程间通信(共享内存)的更多相关文章
- Linux环境进程间通信: 共享内存
Linux环境进程间通信: 共享内存 第一部分 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进 ...
- linux进程间通信-共享内存
转载:http://www.cnblogs.com/fangshenghui/p/4039720.html 一 共享内存介绍 共享内存可以从字面上去理解,就把一片逻辑内存共享出来,让不同的进程去访问它 ...
- Linux下进程间通信--共享内存:最快的进程间通信方式
共享内存: 一.概念: 共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间. 进程A可以即时看到进程B ...
- Linux进程间通信—共享内存
五.共享内存(shared memory) 共享内存映射为一段可以被其他进程访问的内存.该共享内存由一个进程所创建,然后其他进程可以挂载到该共享内存中.共享内存是最快的IPC机制,但由于linux本身 ...
- Windows进程间通信--共享内存映射文件(FileMapping)--VS2012下发送和接收
之前以为两个互不相关的程序a.exe b.exe通信就只能通过网络,人家说可以通过发消息,我还深以为不然,对此,我表示万分惭愧. 之前课本上说的进程间通信,有共享内存.管道等之类的,但没有自己操刀写过 ...
- Linux 进程间通信 共享内存
1.特点: 1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝.如管道当在内核空间创建以后,用户空间需要内存 拷贝,需要拷贝数据,所以效率低. 2)为了在多个进 ...
- linux 进程间通信 共享内存 shmat
系统调用mmap()通过映射一个普通文件实现共享内存.系统V则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信.也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件(这是通过shm ...
- linux 进程间通信 共享内存 mmap
共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反 ...
- win32下进程间通信——共享内存
一.引言 在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯.WIN32 API提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换 ...
随机推荐
- Eclipse设置合适的字体
一直使用Eclipse开发,最近感觉Comic Sans MS不错,但我的eclipse的默认字体里没有. 如果系统里有这个字体的话,那可以很简单的将这个字体添加到Eclipse中: Windows ...
- Tomcat类加载器
1JVM类加载机制 JVM的ClassLoader通过Parent属性定义父子关系,可以形成树状结构.其中引导类.扩展类.系统类三个加载器是JVM内置的. 它们的作用分别是: 1)引导类加载器:使 ...
- 组播报文转发过程RPF
单播报文的转发过程中,路由器并不关心组播源地址,只关心报文中的目的地址,通过目的地址决定向哪个接口转发.在组播中,报文是发送给一组接收者的,这些接收者用一个逻辑地址标识.路由器在接收到报文后,必须根据 ...
- 组播MAC地址转换关系及唯一性处理
组播地址与其对应的组播MAC换算关系如下: 组播MAC=组播MAC标识+组播IP后23位对应的二进制位(32位的IP地址取后23位导致32组IP地址对应的多播IP相同) (IANA把01:00:5 ...
- Gradle version 2.10 is required. Current version is 2.8.
今天在网上下载了EasyPusher-master文件,日期是20160527版本的,但是在我的Android Studio上运行时报错: Error:(1, 1) A problem occurre ...
- iOS单元测试(作用及入门提升)
由于只是一些简单实用的东西,学学还是挺不错的.其实单元测试用的好,开发起来也会快很多.单元测试对于我目前来说,就是为了方便测试一些功能是否正常运行,还有调试接口是否能正常使用.有时候你可能是为了测试某 ...
- [深入React] 2.综述
在开始本教程前,请先查看官方示例:https://github.com/facebook/react/archive/master.zip 里的 examples 目录. 学习react是一个循序渐进 ...
- <有序数组>转化为<按二分法遍历顺序排列的数组>(C++实现)
在进行参数试错时,通常将可能的参数由小到大排列一个个进行测试,这样的测试顺序很多时候不太合理,因此写了一个按二分法遍历顺序排列的算法,通常能更快的找到合适的参数.代码如下: /************ ...
- 解析Xcode把应用程序打包成ipa---解决打包完新版本itunes提示不是有效应用程序的问题
Xcode把应用程序打包成ipa是本文要介绍的内容,不多说,先俩看内容.注意:本方法需要先制作假凭证编译于项目中,否则产生的ipa还是无法于iPhone中运行. 制作方法请参考: http://blo ...
- UITableView的刷新
UITableView的刷新1> 数据刷新的总体步骤* 修改模型数据* 刷新表格(刷新界面) 2> 刷新表格(刷新界面)的方法* 全局刷新(每一行都会重新刷新)- (void)reload ...