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提供了许多函数使我们能够方便高效的进行进程间的通讯,通过这些函数我们可以控制不同进程间的数据交换 ...
随机推荐
- Android客户端实现七牛云存储文件上传
1.简单文件上传 上传模型如下. 1.1获得Token 不管是简单文件上传,还是分片上传.断点续传 都需要首先访问服务器,以获得上传凭证信息Token..用于测试时,可以用本地模拟Token信息(有 ...
- HDU_2021——最少RMB问题
Problem Description 作为杭电的老师,最盼望的日子就是每月的8号了,因为这一天是发工资的日子,养家糊口就靠它了,呵呵但是对于学校财务处的工作人员来说,这一天则是很忙碌的一天,财务处的 ...
- CF#345 div2 A\B\C题
A题: 贪心水题,注意1,1这组数据,坑了不少人 #include <iostream> #include <cstring> using namespace std; int ...
- AOJ 0033 深度优先搜索
题意:按给定顺序从A口放标号位1-10的10个球,利用挡板可以使球落到B或C,问能否使B和C里的球标号从下往上递增. 分析:对于第 i 个球,若a[i]大于B口上方的球,则可放入B口:若a[i]大于C ...
- 司机福利!Uber即将可以自己选目的地接单啦!
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- Java[1] Java学习书籍汇总(转)
原文:http://www.cnblogs.com/hyl8218/p/5067000.html 学习的最好途径就是看书“,这是我自己学习并且小有了一定的积累之后的第一体会.个人认为看书有两点好处: ...
- BootStrap--模态框中 上传图片
问题:在模态框中添加图片并不会得到你上传图片的名称,无法存到数据 下面介绍两个方法,都是可以得到图片名称的. 第一种 前面如何加载模态框就不写了,上篇有写,这里只是为得到图片写的 //需要添加一个 ...
- Redis源代码分析-内存数据结构intset
这次研究了一下intset.研究的过程中,一度看不下过去,可是还是咬牙挺过来了.看懂了也就是那么回事.静下心来,切莫浮躁 Redis为了追求高效,在存储下做了非常多的优化,像intset就是作者为了节 ...
- mysql主从监控
要求:检测myslq从库状态,跳过固定的错误号,每隔30秒检测一次,如果符合条件自动跳过或者是重启从库 1)取出mysql从库的关键字 [root@localhost scripts]# mysql ...
- SUN-LDAP6.3_RHEL 5.0-卸载LDAP
卸载LDAP 1.注销服务器 到目录/ldap/ldapinstance/dscc6/bin下 # ./dsccreg remove-server -h 主机名 /ldap/ldapinstance/ ...