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

                }

            }

        }

    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM