zoukankan      html  css  js  c++  java
  • [转]C#进程间通讯--共享内存篇

    上次发了利用发消息实现的C#进程间的通讯,这次又使用共享内存了,他们应用范围是不同的,共享内存适用于共享大量数据的情况。

    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); 然后分别在AB两个进程中定义如下两个信号量及相关变量;   private Semaphore m_Write;  //可写的信号  private Semaphore m_Read;  //可读的信号  private IntPtr handle;     //文件句柄  private IntPtr addr;       //共享内存地址  uint mapLength;            //共享内存长
    定义这两个信号量是为读写互斥用的。在A进程中创建共享内存: 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); 然后再向共享内存中写入数据: m_Write.WaitOne();byte[] sendStr = Encoding.Default.GetBytes(txtMsg.Text + '/0');//如果要是超长的话,应另外处理,最好是分配足够的内存if(sendStr.Length < mapLength)      Copy(sendStr,addr);m_Read.Release(); 这是在一个单独的方法中实现的,可多次调用,但受信号量的控制。其中txtMsg是一个文本框控件,实际中可用任意字符串,加最后的'/0'是为了让在共享内存中的字符串有一个结束符,否则在内存中取出时是以'/0'为准的,就会出现取多的情况。Copy方法的实现如下: 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 ++;    }   }  } 注意unsafe 关键字,在编译时一定要打开非安全代码开关。最后不要忘了在A进程中关闭共享内存对象,以免内存泄露。    UnmapViewOfFile(addr);   CloseHandle(handle); 要在B进程中读取共享内存中的数据,首先要打开共享内存对象: m_Write = Semaphore.OpenExisting("WriteMap");m_Read = Semaphore.OpenExisting("ReadMap");handle = OpenFileMapping(0x0002,0,"shareMemory"); 读取共享内存中的数据:    m_Read.WaitOne();   string str = MapViewOfFile(handle,FILE_MAP_ALL_ACCESS,0,0,0);   txtMsg.Text = str;   m_Write.Release(); 这里获取了字符串,如果要获取byte数组,请参考上面的Copy函数实现。

    使用微软消息队列实现C#进程间通信 http://tech.ddvip.com/2007-11/119554606737754.html

    在.NET中使用命名管道完成进程间通信

    http://www.hackhome.com/InfoView/Article_121029_2.html


    ---------------------
    作者:申深
    来源:CNBLOGS
    原文:https://www.cnblogs.com/joye-shen/archive/2012/06/16/2551864.html
    版权声明:本文为作者原创文章,转载请附上博文链接!
    内容解析By:CSDN,CNBLOG博客文章一键转载插件

  • 相关阅读:
    bzoj3224
    [洛谷日报第62期]Splay简易教程 (转载)
    bzoj1588
    codeforces467C
    codeforces616B
    codeforces379C
    codeforces545C
    codeforces285C
    codeforces659C
    快读代码level.2
  • 原文地址:https://www.cnblogs.com/dinghw/p/12860361.html
Copyright © 2011-2022 走看看