程序間通訊——共享記憶體
阿新 • • 發佈:2021-01-11
技術標籤: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++; } } } } }