1. 程式人生 > 其它 >程序間通訊——共享記憶體

程序間通訊——共享記憶體

技術標籤:C#和WinFrom

接收端

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : 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 Form1()
        {
            InitializeComponent();
            init();
        }


        ///<summary>/// 初始化共享記憶體資料 建立一個共享記憶體
        ///</summary>
        private void 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);

            threadRed = new Thread(new ThreadStart(ThreadReceive));
            threadRed.Start();
        }

        /// <summary>
        /// 執行緒啟動從共享記憶體中獲取資料資訊 
        /// </summary>
        private void ThreadReceive()
        {
            while (true)
            {
                try
                {
                    //讀取共享記憶體中的資料:
                    //是否有資料寫過來
                    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);
                    this.Invoke((MethodInvoker)(delegate ()
                    { textBox1.Text = str.Trim(); })
                        );
                    /呼叫資料處理方法 處理讀取到的資料
                    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')
                    ;
            }

        }

    }
}

傳送端

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form1 : 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 Form1()
        {
            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++;
                }
            }
        }

    }
}