一、共享内存的帮助类

/**
*┌──────────────────────────────────────────────────────────────┐
*│ 描    述:两个exe程序之间通信_共享内存传递(基础示例,程序中使用时不进一步封装是不够的)                                                  
*│ 作    者:执笔小白                                              
*│ 版    本:1.0                                       
*│ 创建时间:2022-12-06 10:40:56                            
*└──────────────────────────────────────────────────────────────┘
*┌──────────────────────────────────────────────────────────────┐
*│ 命名空间: Communication_Between_exe_ProgramsHelper                              
*│ 类    名:Communication_SharedMemoryHelper                                     
*└──────────────────────────────────────────────────────────────┘
*/
using Newtonsoft.Json;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;

namespace Communication_Between_exe_ProgramsHelper
{
    /// <summary>
    /// 两个exe程序之间通信_共享内存传递(主从运行,不可单独运行)
    /// </summary>
    public class Communication_SharedMemoryHelper
    {
        /*
         * 二进制 100=0x1100100
         * 
         * 注意一:线程或进程间通讯时使用互斥锁
         * //bool mutexCreated;
         * //Mutex mutex = newMutex(true, "testmapmutex", out mutexCreated);  // 创建锁(指定锁名)
         * //try{
         * //    mutex.WaitOne();  // 等待其他程序释放锁
         * //    // 通讯处理...
         * //}
         * //finally{
         * //    mutex.ReleaseMutex();  // 释放锁
         * //}
         * 
         * 注意二:非持久文件映射时,注意MemoryMappedFile不要被GC。
         * 
         */

        #region 非持久文件映射
        /*
         * 1、非持久文件映射
         * 非持久文件是未与磁盘上的源文件关联的内存映射文件。
         * 当最后一个进程使用完此文件后,数据将丢失,并且垃圾回收功能将回收此文件。
         * 可使用非托管对象防止被回收
         */

        private static MemoryMappedFile? mmf_NoKeep;

        /// <summary>
        /// 内存共享_基于流的操作_读-非持久文件映射
        /// </summary>
        /// <param name="mmfName">共享内容对象名</param>
        /// <returns></returns>
        public static MemoryMappedFile_ShareInfo_ViewStream MemoryMappedFile_ViewStream_Read_NoKeep(string mmfName)
        {
            MemoryMappedFile_ShareInfo_ViewStream resultShareInfo = new();

            mmf_NoKeep = MemoryMappedFile.CreateOrOpen(mmfName, 0x1100100, MemoryMappedFileAccess.ReadWrite);  // 打开共享内存区域,大小默认为100MB
            using (MemoryMappedViewStream stream = mmf_NoKeep.CreateViewStream())
            {
                if (stream.CanRead)
                {
                    BinaryReader reader = new(stream);
                    if (JsonConvert.DeserializeObject<MemoryMappedFile_ShareInfo_ViewStream>(reader.ReadString()) is MemoryMappedFile_ShareInfo_ViewStream share)
                    {
                        resultShareInfo = share;
                    }
                }
            }
            return resultShareInfo;
        }

        /// <summary>
        /// 内存共享_基于内存偏移量的操作_读-非持久文件映射
        /// </summary>
        /// <param name="mmfName">共享内容对象名</param>
        /// <returns></returns>
        public static MemoryMappedFile_ShareInfo_ViewAccessor MemoryMappedFile_ViewAccessor_Read_NoKeep(string mmfName)
        {
            MemoryMappedFile_ShareInfo_ViewAccessor resultShareInfo = new();

            mmf_NoKeep = MemoryMappedFile.CreateOrOpen(mmfName, 0x1100100, MemoryMappedFileAccess.ReadWrite);  // 打开共享内存区域,大小默认为100MB
            using (MemoryMappedViewAccessor accessor = mmf_NoKeep.CreateViewAccessor(0, 100))  // 注意这里的偏移量,大小;大小100MB
            {
                int colorSize = Marshal.SizeOf(typeof(MemoryMappedFile_ShareInfo_ViewAccessor));
                accessor.Read(0, out resultShareInfo);  // 读取视图
            }
            return resultShareInfo;
        }

        /// <summary>
        /// 内存共享_基于流的操作_写-非持久文件映射
        /// </summary>
        /// <param name="mmfName">共享内容对象名</param>
        /// <param name="share">写入的内容</param>
        public static bool MemoryMappedFile_ViewStream_Wirte_NoKeep(string mmfName, MemoryMappedFile_ShareInfo_ViewStream shareInfo)
        {
            bool result = false;

            mmf_NoKeep = MemoryMappedFile.CreateOrOpen(mmfName, 0x1100100, MemoryMappedFileAccess.ReadWrite);  // 打开共享内存区域,大小默认为100MB
            using (MemoryMappedViewStream stream = mmf_NoKeep.CreateViewStream())
            {
                result = stream.CanWrite;
                if (result)
                {
                    BinaryWriter writer = new(stream);
                    writer.Write(JsonConvert.SerializeObject(shareInfo));
                }
            }
            return result;
        }

        /// <summary>
        /// 内存共享_基于内存偏移量的操作_写-非持久文件映射
        /// </summary>
        /// <param name="mmfName"></param>
        /// <param name="shareInfo"></param>
        /// <returns></returns>
        public static bool MemoryMappedFile_ViewAccessor_Wirte_NoKeep(string mmfName, MemoryMappedFile_ShareInfo_ViewAccessor shareInfo)
        {
            bool result = false;

            mmf_NoKeep = MemoryMappedFile.CreateOrOpen(mmfName, 0x1100100, MemoryMappedFileAccess.ReadWrite);  // 打开共享内存区域,大小默认为100MB 
            using (MemoryMappedViewAccessor accessor = mmf_NoKeep.CreateViewAccessor(0, 100))  // 注意这里的偏移量,大小;大小100MB
            {
                result = accessor.CanRead;
                if (result)
                {
                    int colorSize = Marshal.SizeOf(typeof(MemoryMappedFile_ShareInfo_ViewAccessor));
                    // 视图操作
                    accessor.Write(0, ref shareInfo);  // 修改视图
                }
            }
            return result;
        }
        #endregion 非持久文件映射

        #region 持久文件映射
        /* 
         * 2、持久文件映射
         * 持久文件是与磁盘上的源文件关联的内存映射文件。
         * 在最后一个进程使用完此文件后,数据将保存到磁盘上的源文件中。这些内存映射文件适合用来处理非常大的源文件。
         * 不需要考虑维护共享内存对象被回收的问题
         */

        /// <summary>
        /// 内存共享_基于流的操作_读-持久文件映射
        /// </summary>
        /// <param name="mmfFile">共享内容对象的文件路径</param>
        /// <param name="mmfName">共享内容对象名</param>
        /// <returns></returns>
        public static MemoryMappedFile_ShareInfo_ViewStream MemoryMappedFile_ViewStream_Read_Keep(string mmfFile, string mmfName, long defaultSize = 0x1100100)
        {
            MemoryMappedFile_ShareInfo_ViewStream resultShareInfo = new();

            using (MemoryMappedFile mmf_Keep = MemoryMappedFile.CreateFromFile(mmfFile, FileMode.OpenOrCreate, mmfName, defaultSize))  // "D:\\内存映射文件.data",默认100MB
            {
                using (MemoryMappedViewStream stream = mmf_Keep.CreateViewStream())
                {
                    if (stream.CanRead)
                    {
                        BinaryReader reader = new(stream);
                        if (JsonConvert.DeserializeObject<MemoryMappedFile_ShareInfo_ViewStream>(reader.ReadString()) is MemoryMappedFile_ShareInfo_ViewStream share)
                        {
                            resultShareInfo = share;
                        }
                    }
                }
            }
            return resultShareInfo;
        }

        /// <summary>
        /// 内存共享_基于内存偏移量的操作_读-持久文件映射
        /// </summary>
        /// <param name="mmfFile">共享内容对象的文件路径</param>
        /// <param name="mmfName">共享内容对象名</param>
        /// <returns></returns>
        public static MemoryMappedFile_ShareInfo_ViewAccessor MemoryMappedFile_ViewAccessor_Read_Keep(string mmfFile, string mmfName, long defaultSize = 0x1100100)
        {
            MemoryMappedFile_ShareInfo_ViewAccessor resultShareInfo = new();

            using (MemoryMappedFile mmf_Keep = MemoryMappedFile.CreateFromFile(mmfFile, FileMode.OpenOrCreate, mmfName, defaultSize))  // "D:\\内存映射文件.data",默认100MB
            {
                using (MemoryMappedViewAccessor accessor = mmf_Keep.CreateViewAccessor(0, 100))  // 注意这里的偏移量,大小;大小需要调整
                {
                    int colorSize = Marshal.SizeOf(typeof(MemoryMappedFile_ShareInfo_ViewAccessor));
                    // 视图操作
                    accessor.Read(0, out resultShareInfo);  // 读取视图
                }
            }

            return resultShareInfo;
        }

        /// <summary>
        /// 内存共享_基于流的操作_写-持久文件映射
        /// </summary>
        /// <param name="mmfFile">共享内容对象的文件路径</param>
        /// <param name="mmfName">共享内容对象名</param>
        /// <param name="share">写入的内容</param>
        public static bool MemoryMappedFile_ViewStream_Wirte_Keep(string mmfFile, string mmfName, MemoryMappedFile_ShareInfo_ViewStream shareInfo, long defaultSize = 0x1100100)
        {
            bool result = false;
            using (MemoryMappedFile mmf_Keep = MemoryMappedFile.CreateFromFile(mmfFile, FileMode.OpenOrCreate, mmfName, defaultSize))  // "D:\\内存映射文件.data",默认100MB
            {
                using (MemoryMappedViewStream stream = mmf_Keep.CreateViewStream())
                {
                    result = stream.CanWrite;
                    if (result)
                    {
                        BinaryWriter writer = new(stream);
                        writer.Write(JsonConvert.SerializeObject(shareInfo));
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 内存共享_基于内存偏移量的操作_写-持久文件映射
        /// </summary>
        /// <param name="mmfFile">共享内容对象的文件路径</param>
        /// <param name="mmfName">共享内容对象名</param>
        /// <param name="share">写入的内容(二进制,单位MB)</param>
        public static bool MemoryMappedFile_ViewAccessor_Wirte_Keep(string mmfFile, string mmfName, MemoryMappedFile_ShareInfo_ViewAccessor shareInfo, long defaultSize = 0x1100100)
        {
            bool result = false;

            using (MemoryMappedFile mmf_Keep = MemoryMappedFile.CreateFromFile(mmfFile, FileMode.OpenOrCreate, mmfName, defaultSize))  // "D:\\内存映射文件.data",默认100MB
            {
                using (MemoryMappedViewAccessor accessor = mmf_Keep.CreateViewAccessor(0, 100))  // 注意这里的偏移量,大小;大小需要调整
                {
                    result = accessor.CanRead;
                    if (result)
                    {
                        int colorSize = Marshal.SizeOf(typeof(MemoryMappedFile_ShareInfo_ViewAccessor));
                        // 视图操作
                        accessor.Write(0, ref shareInfo);  // 修改视图
                    }
                }
            }
            return result;
        }
        #endregion 持久文件映射

        /// <summary>
        /// 共享内存_基于流的
        /// </summary>
        public class MemoryMappedFile_ShareInfo_ViewStream
        {
            /// <summary>
            /// 标识ID
            /// </summary>
            public string SessionIdGUID { set; get; } = string.Empty;

            /// <summary>
            /// 创建时间
            /// </summary>
            public DateTime CreateTime { set; get; } = DateTime.Now;

            /// <summary>
            /// 自定义的共享信息
            /// </summary>
            public object InfoData { set; get; } = new object();
        }

        /// <summary>
        /// 共享内存_基于偏移量的
        /// </summary>
        public struct MemoryMappedFile_ShareInfo_ViewAccessor
        {
            /// <summary>
            /// 标识ID
            /// </summary>
            public int SessionIdGUID { set; get; } = 0;

            /// <summary>
            /// 创建时间
            /// </summary>
            public DateTime CreateTime { set; get; } = DateTime.Now;

            /// <summary>
            /// 自定义的共享信息
            /// </summary>
            public long InfoData { set; get; } = 0;

            public MemoryMappedFile_ShareInfo_ViewAccessor()
            {

            }
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.
  • 272.
  • 273.
  • 274.
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
  • 280.
  • 281.
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
  • 287.
  • 288.
  • 289.
  • 290.
  • 291.
  • 292.
  • 293.
  • 294.
  • 295.
  • 296.
  • 297.

二、发送端:

/// <summary>
        /// 共享内存传递_发送
        /// </summary>
        private void btnSedMsg_SharedMemo_Click(object sender, EventArgs e)
        {
            bool result = false;

            if (radIsStream.Checked && chkIsKeep.Checked)
            {
                MemoryMappedFile_ShareInfo_ViewStream shareInfo = new();
                shareInfo.SessionIdGUID = "1";
                shareInfo.CreateTime = DateTime.Now;
                shareInfo.InfoData = txtMsg_SharedMemo.Text.Trim();

               // result = MemoryMappedFile_ViewStream_Wirte_Keep(txtShareFilePath.Text.Trim(), txtShareName.Text.Trim(), shareInfo); 
               result = MemoryMappedFile_ViewStream_Wirte_Keep(@"D:\ShareTest.data", @"ImgA", shareInfo);
            }  // 内存共享_基于流的操作_写-持久文件映射
            else if (radIsStream.Checked && !chkIsKeep.Checked)
            {
                MemoryMappedFile_ShareInfo_ViewStream shareInfo = new();
                shareInfo.SessionIdGUID = "1";
                shareInfo.CreateTime = DateTime.Now;
                shareInfo.InfoData = txtMsg_SharedMemo.Text.Trim();

                result = MemoryMappedFile_ViewStream_Wirte_NoKeep(txtShareName.Text.Trim(), shareInfo);
            }  // 内存共享_基于流的操作_写-非持久文件映射
            else if (!radIsStream.Checked && chkIsKeep.Checked)
            {
                MemoryMappedFile_ShareInfo_ViewAccessor shareInfo = new();
                shareInfo.SessionIdGUID = 1;
                shareInfo.CreateTime = DateTime.Now;
                shareInfo.InfoData = Convert.ToInt64(txtMsg_SharedMemo.Text.Trim());

                //result = MemoryMappedFile_ViewAccessor_Wirte_Keep(txtShareFilePath.Text.Trim(), txtShareName.Text.Trim(), shareInfo);
                result = MemoryMappedFile_ViewAccessor_Wirte_Keep(@"D:\ShareTest.data", @"ImgA", shareInfo);
            }  // 内存共享_基于内存偏移量的操作_写-持久文件映射
            else if (!radIsStream.Checked && !chkIsKeep.Checked)
            {
                MemoryMappedFile_ShareInfo_ViewAccessor shareInfo = new();
                shareInfo.SessionIdGUID = 1;
                shareInfo.CreateTime = DateTime.Now;
                shareInfo.InfoData = Convert.ToInt64(txtMsg_SharedMemo.Text.Trim());

                result = MemoryMappedFile_ViewAccessor_Wirte_NoKeep(txtShareName.Text.Trim(), shareInfo);  //
            }  // 内存共享_基于内存偏移量的操作_写-非持久文件映射
            txtMsg_SharedMemo.Text += ";" + result.ToString();
        }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.

三、接收端:

/// <summary>
        /// 共享内存方式-手动获取(根据需要加互斥锁或进程内线程锁)
        /// </summary>
        private void BtnManualGet_Click(object sender, EventArgs e)
        {
            if (radIsStream.Checked && chkIsKeep.Checked)  // 内存共享_基于流的操作_写-持久文件映射
            {
                MemoryMappedFile_ShareInfo_ViewStream shareInfo = MemoryMappedFile_ViewStream_Read_Keep(txtShareFilePath.Text.Trim(), txtShareName.Text.Trim());
                if (shareInfo != null && shareInfo.InfoData is string infoData)
                {
                    rTxtShareMemo_msg.Text = "信息序号:" + shareInfo.SessionIdGUID + ";发送时间:" + shareInfo.CreateTime + ";内容:" + (!string.IsNullOrEmpty(infoData) ? infoData : string.Empty);
                }
                else
                {
                    rTxtShareMemo_msg.Text = "未获取到数据!";
                }
            }
            else if (radIsStream.Checked && !chkIsKeep.Checked)  // 内存共享_基于流的操作_写-非持久文件映射
            {
                MemoryMappedFile_ShareInfo_ViewStream shareInfo = MemoryMappedFile_ViewStream_Read_NoKeep(txtShareName.Text.Trim());
                if (shareInfo != null && shareInfo.InfoData is string infoData)
                {
                    rTxtShareMemo_msg.Text = "信息序号:" + shareInfo.SessionIdGUID + ";发送时间:" + shareInfo.CreateTime + ";内容:" + (!string.IsNullOrEmpty(infoData) ? infoData : string.Empty);
                }
                else
                {
                    rTxtShareMemo_msg.Text = "未获取到数据!";
                }
            }
            else if (!radIsStream.Checked && chkIsKeep.Checked)  // 内存共享_基于内存偏移量的操作_写-持久文件映射
            {
                MemoryMappedFile_ShareInfo_ViewAccessor shareInfo = MemoryMappedFile_ViewAccessor_Read_Keep(txtShareFilePath.Text.Trim(), txtShareName.Text.Trim());
                rTxtShareMemo_msg.Text = "信息序号:" + shareInfo.SessionIdGUID + ";发送时间:" + shareInfo.CreateTime + ";内容:" + (long)shareInfo.InfoData;
            }
            else if (!radIsStream.Checked && !chkIsKeep.Checked)  // 内存共享_基于内存偏移量的操作_写-非持久文件映射
            {
                MemoryMappedFile_ShareInfo_ViewAccessor shareInfo = MemoryMappedFile_ViewAccessor_Read_NoKeep(txtShareName.Text.Trim());  //

                rTxtShareMemo_msg.Text = "信息序号:" + shareInfo.SessionIdGUID + ";发送时间:" + shareInfo.CreateTime + ";内容:" + (long)shareInfo.InfoData;
            }
        }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.

作者:꧁执笔小白꧂