当前位置:首页 > Windows程序 > 正文

C# 进程间通信(共享内存)

2024-03-31 Windows程序

进程间通信的方式有很多,常用的方式有:

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 = -1;

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,  //0

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();

}   

// 初始化共享内存数据 创建一个共享内存

privatevoid init()

{

m_Write = new Semaphore(1, 1, "WriteMap");//开始的时候有一个可以写

m_Read = new Semaphore(0, 1, "ReadMap");//没有数据可读

mapLength = 1024;

IntPtr hFile = new IntPtr(INVALID_HANDLE_VALUE);

handle = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, mapLength, "shareMemory");

addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

//handle = OpenFileMapping(0x0002, 0, "shareMemory");

//addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

threadRed = new Thread(new ThreadStart(ThreadReceive));

threadRed.Start();

}

       // 线程启动从共享内存中获取数据信息

        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[100];

byteCopy(byteStr, addr);

string str = Encoding.Default.GetString(byteStr, 0, 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 = -1;

const int PAGE_READWRITE = 0x04;

//共享内存

[DllImport("Kernel32.dll", EntryPoint = "CreateFileMapping")]

private static extern IntPtr CreateFileMapping(IntPtr hFile, //HANDLE hFile,

UInt32 lpAttributes,//LPSECURITY_ATTRIBUTES lpAttributes,  //0

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 = 1024;

}

private void button1_Click(object sender, EventArgs e)

{

try

{

m_Write = Semaphore.OpenExisting("WriteMap");

m_Read = Semaphore.OpenExisting("ReadMap");

handle = OpenFileMapping(FILE_MAP_WRITE, 0, "shareMemory");

addr = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);

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 = 0; i < byteSrc.Length; i++)

{

*pDst = *psrc;

pDst++;

psrc++;

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/42995.html

Jm-杰米博客Jamie
草根站长的技术交流乐园!IT不会不要紧快来好好学习吧!
  • 20786文章总数
  • 7494595访问次数
  • 建站天数
  • 友情链接