1. 程式人生 > >C#共享記憶體類改進版

C#共享記憶體類改進版

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

相關推薦

C#共享記憶體改進

ShareMem.cs using System;using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices;using System.Threading;

C#共享記憶體兩個程序軟體互相讀寫實現

我在網上找了很多原始碼,沒有一個可以用2個程式實現互相讀寫的共享記憶體功能,一般只能單向傳遞,沒有任何意義,於是我自己封裝了一個類,但是看起來沒任何問題,就是不能共享,現在我把程式碼貼出來,請大神幫忙看看 using System; using System.IO; using System

共享記憶體操作 C 原始碼

using System;using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices;namespace ShareMemLib{    publicclass ShareMem    {   

C Primer Plus (第五)中文版——第 12 章 儲存、連結和記憶體管理

12.1  儲存類 12.1.1  作用域 定義:作用域描述了程式中可以訪問一個識別符號的一個或多個區域。 分類: 程式碼塊作用域:在程式碼塊中定義的變數具有程式碼塊作用域,從定義處到包含該定義的程式碼塊的末尾,該變數可見。 函式原型作用域:在函式原型

標準C++std::string的記憶體共享和Copy-On-Write技術

1、概念 Scott Meyers在《More Effective C++》中舉了個例子,不知你是否還記得?在你還在上學的時候,你的父母要你不要看電視,而去複習功課,於是你把自己關在房間裡,做出一副正在複習功課的樣子,其實你在幹著別的諸如給班上的某位女生寫情書之類的

【轉】標準C++std::string的內存共享和Copy-On-Write技術

信息 在哪裏 主程序 分析 ash 3.4 alloc 是否 今天 1、 概念 Scott Meyers在《More Effective C++》中舉了個例子,不知你是否還記得?在你還在上學的時候,你的父母要你不要看電視,而去復習功課,於是你

(排序演算法)linux c語言實現選擇排序演算法(氣泡排序的略微改進

 快速排序演算法和氣泡排序演算法是差不多的,都是要兩層迴圈,外迴圈是要比較的個數,其實就是元素的個數,內迴圈就是外層那個標記和其他的比較大小, 氣泡排序是相鄰的兩個,兩兩比較,最後交換出一個最大或者最小值, 快速排序是在氣泡排序的基礎上,找出那個最小的或者最大的,但是不是直接交換,

(排序演算法)linux c語言實現快速排序(氣泡排序的改進

 快速排序演算法是對氣泡排序演算法的一種改進,氣泡排序是對單個元素的升降,快速排序是對所有元素的升降,不過這個升降是取了某一個標準的前提下,在本文程式碼中,就以a[i],其實就是以最左邊的元素為參考,比較交換之後,將這個參考元素放到分界的地方,即i的位置。 程式碼如下,裡面有比較詳細的

c/c++ linux 程序間通訊系列4,使用共享記憶體

linux 程序間通訊系列4,使用共享記憶體 1,建立共享記憶體,用到的函式shmget, shmat, shmdt 函式名 功能描述 shmget 建立共享記憶體,返回pic key

C++:通過C++程式碼簡單理解程序間的通訊機制:共享記憶體

下面用共享對映檔案的方式實現程序間通訊,程式碼可以執行。 一、淺理解 每個程序有自己獨立的空間,一個程序無法訪問其他程序的資料。就好像兩個是互不干涉的個體,想讓它們進行通訊(交換資料),就必須有一段它們都可以訪問到的空間,作為中間介質。在計算機中,可以存放資料的地方分為記憶體和硬

C#使用MemoryStream讀寫記憶體

MemoryStream和BufferedStream都派生自基類Stream,因此它們有很多共同的屬性和方法,但是每一個類都有自己獨特的用法。這兩個類都是實現對記憶體進行資料讀寫的功能,而不是對永續性儲存器進行讀寫。   讀寫記憶體-MemoryStream類 MemoryStream類用於

Android呼叫C++實現共享記憶體(Native層)

MemoryFile是java層封裝的介面,它實現共享記憶體主要呼叫瞭如下函式: int fd = open("/dev/ashmem",O_RDWR); ioctl(fd, ASHMEM_SET_NAME,name); ioctl(fd,ASHMEM_SET

C++巢狀在單例模式Singleton中自動釋放堆記憶體的應用

首先放出單例模式中的程式碼: singleton.h #ifndef SINGLETON_H #define SINGLETON_H #include <iostream> #include

c++中 子物件與父物件的記憶體關係

  問題:如題。假設有父類A與子類B A例項化一個物件a   B例項化一個物件b 那麼在記憶體中 a與b的地址關係是什麼。是他們的首地址都一樣嗎? 解答: 他們是沒有必然關係的。就跟你隨便生成另外兩個其他型別的變數一樣。當然,你例項化的物件b跟A有關係。 b物件開頭的部分4

C# 基礎(十四)C#單例模式:首先介紹 單執行緒、多執行緒、加鎖 單例模式。然後介紹單例模式的執行緒同步:多執行緒有序訪問共享記憶體

一、簡介 本篇文章將介紹如何使用單例模式,也就是類的例項化,在整個專案的生命週期內,只例項化一次。在單例模式中,往往可以看到如SourceCode.cs:這樣的結構的。 SourceCode.cs: public class Singleton { private static

C++中的所佔記憶體空間總結(其中有一段關於成員函式處於程式碼段的解釋) 2011-12-9 16:16

#include<iostream.h> class a {}; class b{}; class c:public a{ virtual void fun()=0; }; class d:public b,public c{}; int main() { cout<&

Windows or Linux環境下利用“共享記憶體”實現程序間通訊的C/C++程式碼

程序A對應的程式: #include <iostream> #include <windows.h> using namespace std; #define BUF_SIZE 1025 char szName[] = "NameOfMappi

golang 結合cgo 操作共享記憶體,包括虛擬記憶體mmap記憶體shm

如下是原始碼實現直接編譯即可使用: //author sam by 20170621 // 使用示例: // package utils // import ( // "fmt" // u "lpaiche.com/utils" // "testi

c#實現記憶體對映檔案共享記憶體

記憶體對映檔案是利用虛擬記憶體把檔案對映到程序的地址空間中去,在此之後程序操作檔案,就像操作程序空間裡的地址一樣了,比如使用c語言的 memcpy等記憶體操作的函式。這種方法能夠很好的應用在需要頻繁處理一個檔案或者是一個大檔案的場合,這種方式處理IO效率比普通IO效率要高

Windows上C++使用共享記憶體進行程序間通訊

共享記憶體 (也叫記憶體對映檔案) 主要是通過對映機制實現的 , Windows 下程序的地址空間在邏輯上是相互隔離的 , 但在物理上卻是重疊的 ; 所謂的重疊是指同一塊記憶體區域可能被多個程序同時使用