原文
改进说明及源码实例下载见:
ShareMem.cs
using System;
using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices;using System.Threading;using System.IO;namespace ShareMemLib
{ public class ShareMem { [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr CreateFileMapping(int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);[DllImport("kernel32", EntryPoint = "GetLastError")]
public static extern int GetLastError();const int ERROR_ALREADY_EXISTS = 183;
const int FILE_MAP_COPY = 0x0001;
const int FILE_MAP_WRITE = 0x0002; const int FILE_MAP_READ = 0x0004; const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004;const int PAGE_READONLY = 0x02;
const int PAGE_READWRITE = 0x04; const int PAGE_WRITECOPY = 0x08; const int PAGE_EXECUTE = 0x10; const int PAGE_EXECUTE_READ = 0x20; const int PAGE_EXECUTE_READWRITE = 0x40;const int SEC_COMMIT = 0x8000000;
const int SEC_IMAGE = 0x1000000; const int SEC_NOCACHE = 0x10000000; const int SEC_RESERVE = 0x4000000;const int INVALID_HANDLE_VALUE = -1;
IntPtr m_hSharedMemoryFile = IntPtr.Zero;
IntPtr m_pwData = IntPtr.Zero; IntPtr m_pwDataWrite = IntPtr.Zero; IntPtr m_pwDataRead = IntPtr.Zero; bool m_bAlreadyExist = false; bool m_bInit = false; long m_MemSize = 0; int m_length = 0; int m_count = 0; const int infoSize = 50; Semaphore semRead; Semaphore semWrite; Semaphore semWriteLength; String m_pathMSGCSV = "Messages.csv";public ShareMem()
{ } ~ShareMem() { Close(); }///
/// 初始化共享内存 /// /// 共享内存名称 /// 共享内存大小 /// public int Init(string strName, long lngSize) { if (lngSize <= 0 || lngSize > 0x00800000) lngSize = 0x00800000; m_MemSize = lngSize; if (strName.Length > 0) { //创建内存共享体(INVALID_HANDLE_VALUE) m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, (uint)PAGE_READWRITE, 0, (uint)lngSize, strName);if (GetLastError() == ERROR_ALREADY_EXISTS) //已经创建
{ m_bAlreadyExist = true; m_hSharedMemoryFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, strName); }if (m_hSharedMemoryFile == IntPtr.Zero)
{ m_bAlreadyExist = false; m_bInit = false; return 2; //创建共享体失败 } else { if (GetLastError() == ERROR_ALREADY_EXISTS) //已经创建 { m_bAlreadyExist = true; } else //新创建 { m_bAlreadyExist = false; } } //--------------------------------------- //创建内存映射 m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_ALL_ACCESS, 0, 0, (uint)lngSize); m_pwDataWrite = m_pwData; m_pwDataRead = (IntPtr)(m_pwData.GetHashCode() + infoSize); if (m_pwData == IntPtr.Zero) { m_bInit = false; CloseHandle(m_hSharedMemoryFile); return 3; //创建内存映射失败 } else { m_bInit = true; if (m_bAlreadyExist == false) { //初始化 } } //---------------------------------------- } else { return 1; //参数错误 }SetSemaphore();
if (m_bAlreadyExist == false) { WriteLengthAndCount(0, 0); } return 0; //创建成功 }///
/// 关闭共享内存 /// public void Close() { if (m_bInit) { UnmapViewOfFile(m_pwData); CloseHandle(m_hSharedMemoryFile); } }public bool SetSemaphore()
{ try { semRead = Semaphore.OpenExisting("ReadShareMemory"); semWrite = Semaphore.OpenExisting("WriteShareMemory"); semWriteLength = Semaphore.OpenExisting("WriteLengthShareMemory"); } catch (Exception) { semRead = new Semaphore(0, 1, "ReadShareMemory"); semWrite = new Semaphore(1, 1, "WriteShareMemory"); semWriteLength = new Semaphore(1, 1, "WriteLengthShareMemory"); } return true; }/**
public int ReadLength() { Byte[] bytData = new Byte[infoSize]; if (infoSize > m_MemSize) return 2; //超出数据区 if (m_bInit) { Marshal.Copy(m_pwData, bytData, 0, infoSize); } else { return 1; //共享内存未初始化 } String str = System.Text.Encoding.Unicode.GetString(bytData).Trim('/0'); m_length = System.Convert.ToInt32(str); return 0; //读成功 }public int WriteLength(int length)
{ semWriteLength.WaitOne(); if (infoSize > m_MemSize) return 2; //超出数据区 String strLength = System.Convert.ToString(length); Byte[] bytData = System.Text.Encoding.Unicode.GetBytes(strLength); if (m_bInit) { Marshal.Copy(bytData, 0, m_pwData, bytData.Length); } else { semWriteLength.Release(); return 1; //共享内存未初始化 } semWriteLength.Release(); return 0; } **/public int ReadLengthAndCount()
{ Byte[] bytData = new Byte[infoSize]; if (infoSize > m_MemSize) return 2; //超出数据区 if (m_bInit) { Marshal.Copy(m_pwData, bytData, 0, infoSize); } else { return 1; //共享内存未初始化 } String str = System.Text.Encoding.Unicode.GetString(bytData).Trim('/0'); String[] strs = System.Text.RegularExpressions.Regex.Split(str, "/0"); m_length = System.Convert.ToInt32(strs[0]); m_count = System.Convert.ToInt32(strs[1]); return 0; //读成功 }public int WriteLengthAndCount(int length, int count)
{ semWriteLength.WaitOne(); if (infoSize > m_MemSize) return 2; //超出数据区 String strLengthAndCount = System.Convert.ToString(length) + "/0" + System.Convert.ToString(count); Byte[] bytData = System.Text.Encoding.Unicode.GetBytes(strLengthAndCount); if (m_bInit) { /** Byte[] byteZero = new Byte[infoSize]; for (int i = 0; i < infoSize; i++) { byteZero[i] = (Byte)'/0'; } Marshal.Copy(byteZero, 0, m_pwData, infoSize); * **/ Marshal.Copy(bytData, 0, m_pwData, bytData.Length); } else { semWriteLength.Release(); return 1; //共享内存未初始化 } semWriteLength.Release(); return 0; }///
/// 读数据 /// /// 数据 /// 起始地址 /// 个数 /// public int Read(ref byte[] bytData) { ReadLengthAndCount(); if (m_length > m_MemSize) return 2; //超出数据区 if (m_bInit) { Marshal.Copy(m_pwDataRead, bytData, 0, m_length); } else { return 1; //共享内存未初始化 } return 0; //读成功 }///
/// 写数据 /// /// 数据 /// 起始地址 /// 个数 /// public int Write(byte[] bytData, int lngSize) { semWrite.WaitOne(); ReadLengthAndCount(); if (m_length + lngSize > m_MemSize) { System.Windows.Forms.MessageBox.Show("Share memory is full. " + (m_length + lngSize) + ">" + m_MemSize); semWrite.Release(); return 2; //超出数据区 } if (m_bInit) { m_pwDataWrite = (IntPtr)(m_pwData.GetHashCode() + m_length + infoSize); Marshal.Copy(bytData, 0, m_pwDataWrite, lngSize); m_length += lngSize; m_count++; } else { semWrite.Release(); return 1; //共享内存未初始化 } WriteLengthAndCount(m_length, m_count); semWrite.Release(); return 0; //写成功 }public int GetLength()
{ ReadLengthAndCount(); return this.m_length; }public int GetCount()
{ ReadLengthAndCount(); return this.m_count; }public int ReadCSV()
{ try { if (!File.Exists(m_pathMSGCSV)) File.CreateText(m_pathMSGCSV).Close();StreamReader sr = System.IO.File.OpenText(m_pathMSGCSV);
while (!sr.EndOfStream) { String strLine = sr.ReadLine(); if (!System.String.IsNullOrEmpty(strLine)) { strLine += "/0"; Byte[] data = System.Text.Encoding.Unicode.GetBytes(strLine); Write(data, data.Length); } } sr.Close(); } catch (Exception e) { System.Windows.Forms.MessageBox.Show("Error:ReadCSV()" + e); return 1; } return 0; }public int WriteCSV()
{ try { StreamWriter sw = System.IO.File.AppendText(m_pathMSGCSV); ReadLengthAndCount(); Byte[] btydata = new Byte[m_length]; Read(ref btydata); String strOut = System.Text.Encoding.Unicode.GetString(btydata).Trim('/0'); String[] sArray = System.Text.RegularExpressions.Regex.Split(strOut, "/0"); foreach (String str in sArray) { if (!String.IsNullOrEmpty(str)) sw.WriteLine(str); } sw.Flush(); sw.Close(); } catch (Exception) { System.Windows.Forms.MessageBox.Show("Error:WriteCSV()"); return 1; } return 0; }public int Clear()
{ ReadLengthAndCount(); if (infoSize + m_length > m_MemSize) return 2; //超出数据区 if (m_bInit) { Byte[] byteZero = new Byte[infoSize + m_length]; for (int i = 0; i < infoSize; i++) { byteZero[i] = (Byte)'/0'; } Marshal.Copy(byteZero, 0, m_pwData, infoSize + m_length); m_pwDataWrite = m_pwData; m_length = 0; m_count = 0; WriteLengthAndCount(0, 0); } return 0; } }}
Form1.cs
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 ShareMemLib;namespace ShareMemory
{ public partial class frmMain : Form { ShareMem MemDB = new ShareMem(); const int m_memSize = 4096000;public frmMain()
{ InitializeComponent(); btnInit.Enabled = true; btnWrite.Enabled = false; btnRead.Enabled = false; txtInput.Text = "AAA"; }private void ReadTest()
{ String str = ReadToStr(); String[] strArray = System.Text.RegularExpressions.Regex.Split(str, "/0"); lstData.Items.Clear(); foreach (String s in strArray) { lstData.Items.Add(s); } }private String ReadToStr()
{ int currentLength = MemDB.GetLength(); int currentCount = MemDB.GetCount(); Byte[] data = new Byte[currentLength]; MemDB.Read(ref data); lblUsedSize.Text = currentLength.ToString(); lblCount.Text = currentCount.ToString(); return System.Text.Encoding.Unicode.GetString(data); }private void WriteStr(String str)
{ btnWrite.Enabled = false; try { Byte[] data = System.Text.Encoding.Unicode.GetBytes(str); MemDB.Write(data, data.Length); } catch (Exception) { MessageBox.Show("Error in WriteStr"); } btnWrite.Enabled = true; }private void btnInit_Click(object sender, EventArgs e)
{ if (MemDB.Init("YFMemTest", m_memSize) != 0) { //初始化失败 MessageBox.Show("初始化失败"); } else { btnInit.Enabled = false; btnWrite.Enabled = true; btnRead.Enabled = true; } lblTotalSize.Text = m_memSize.ToString(); }private void btnClear_Click(object sender, EventArgs e)
{ MemDB.Clear(); ReadTest(); }private void btnReadCSV_Click(object sender, EventArgs e)
{ MemDB.ReadCSV(); ReadTest(); }private void btnWriteCSV_Click(object sender, EventArgs e)
{ MemDB.WriteCSV(); MemDB.Clear(); ReadTest(); }private void btnRead_Click(object sender, EventArgs e)
{ ReadTest(); }private void btnWrite_Click(object sender, EventArgs e)
{ //String str = "B000" + (i++) + ",1,1,2008,success/0"; String str = txtInput.Text + System.DateTime.Now.ToString(",yyyMMdd,HHmmss,fff/0"); WriteStr(str);ReadTest();
} }}