C# 進程間通訊(共享內存)

原文: C# 進程間通訊(共享內存)

進程間通訊的方式有不少,經常使用的方式有:html

1.共享內存(內存映射文件,共享內存DLL)。c++

2.命名管道和匿名管道。安全

3.發送消息 app

本文是記錄共享內存的方式進行進程間通訊,首先要創建一個進程間共享的內存地址,建立好共享內存地址後,一個進程向地址中寫入數據,另外的進程從地址中讀取數據。post

在數據的讀寫的過程當中要進行進程間的同步。ui

進程間數據同步能夠有如下的方式url

1. 互斥量Mutexspa

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

       ///<summary>/// 初始化共享內存數據 建立一個共享內存
        
///</summary>privatevoid init()
        {
            m_Write = new Semaphore(11"WriteMap");//開始的時候有一個能夠寫
            m_Read = new Semaphore(01"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, 000);

            //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[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,  000);

                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++;                 }             }         }    } }
相關文章
相關標籤/搜索