如何在 c#.Net 4 中正确使用内存共享

本文关键字:内存 共享 Net | 更新日期: 2023-09-27 18:36:55

我不知道

是因为旧帖子还是缺乏理解,但是在使用内存映射时,我似乎遇到了各种不良信息。净4. 也许只要.Net4 以测试版发布,每个人都开始发布有关它的信息,并且在 .Net4测试版? 或者也许我只是不知道我在说什么,他们没问题,但我似乎无法弄清楚使用内存映射的正确方法。 我正在寻找一种在两个应用程序上使用相同的代码的方法,因此代码是通用的,并且两个应用程序中的一个不会被视为主应用程序(这创建了另一个应用程序需要的东西)。 示例 1 是我不想实现的想法的一个主要示例(它只是作为我发现的一个例子)。

最后,我希望两个应用程序都一遍又一遍地运行,访问内存流(内存映射)以根据需要读取和写入数据。 当最后一个使用内存映射的应用程序退出时,应关闭并删除映射。

我已经看到以下示例试图展示如何正确使用内存映射。 我不知道他们都在做什么,但他们使用的重载似乎也是错误的。 :/

示例 1:

这将在首次创建内存的 app1 上使用.exe 上。

using System.IO;
using System.IO.MemoryMappedFile;
MemoryMappedFile MemoryMapped = MemoryMappedFile.CreateFromFile(
  new FileStream(@"C:'temp'Map.mp", FileMode.Create),
  "MyMemMapFile",
  1024 * 1024,
  MemoryMappedFileAccess.ReadWrite
);
//Write to the memory map
MemoryMappedViewAccessor FileMapView = MemoryMapped.CreateViewAccessor();
int Number = 1234;
FileMapView.Write(0, Number);
FileMapView.Write<Container>(4, ref MyContainer);

这将在 app2 上使用.exe稍后将访问内存。

using System.IO;
using System.IO.MemoryMappedFile;
MemoryMappedFile MemoryMapped = MemoryMappedFile.CreateOrOpen(
  new FileStream(
    @"C:'temp'Map.mp",
    FileMode.Create),
  "MyMemMapFile",
  1024 * 1024,
  MemoryMappedFileAccess.ReadWrite
);
// Create the map view and read it
using (MemoryMappedViewAccessor FileMap = MemoryMapped.CreateViewAccessor())
{
  Container NewContainer = new Container();
  FileMap.Read<Container>(4, out NewContainer);
}

示例 2:

using System.IO;
using System.IO.MemoryMappedFiles;
class Test
{
    static void Main()
    {
        FileStream file = File.OpenRead("Test.cs");
        using (MemoryMappedFile mappedFile = MemoryMappedFile.CreateFromFile
               (file, "PEIMAGE", file.Length, MemoryMappedFileAccess.Read))
        {
            using (var viewStream = mappedFile.CreateViewStream
                   (0, file.Length, MemoryMappedFileAccess.Read))
            {
                // read from the view stream
            }
        }
    }
}

如何在 c#.Net 4 中正确使用内存共享

在其他地方做了一堆研究之后,试图清除多年来不正确的旧代码(回到.Net4 测试版)我设法想出了以下内容。 这给出了如何处理内存映射、内存视图流、读取方法和写入方法的基本示例。 在此示例中,我还使用用户定义的结构将数据从一个应用程序传递到另一个应用程序。

如何在应用程序#1中使用它(写入)

假设我们希望应用程序 #1 将一些数据写入内存流。 在连接到内存流后的Form_Load中,只需使用如下所示的内容...

UpdateInfoPacket packet = new UpdateInfoPacket();
packet.JobName = "This is my test job.";
packet.NumberOfFiles = 40;
packet.Status = 'F';
WriteMemoryMap(packet);

如何在应用程序中使用它 #2 (阅读)

假设我们希望应用程序 #2 从内存流中读取一些数据。 在连接到内存流后的Form_Load中,只需使用如下所示的内容...

UpdateInfoPacket packet;
ReadMemoryMap(out packet);

完整解决方案

using System;
using System.Windows.Forms;
using System.IO.MemoryMappedFiles;
using System.IO;
using System.Runtime.InteropServices;
namespace MyMemoryApplication
{
    public partial class Form1 : Form
    {
        private struct UpdateInfoPacket
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 100)]
            public string JobName;
            public char Status;
            public int NumberOfFiles;
        }
        private MemoryMappedFile m_memMap = null;
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            m_memMap = ConnectToMemoryMap("MyMemoryMapName");
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (m_memMap != null) m_memMap.Dispose();
        }
        private MemoryMappedFile ConnectToMemoryMap(string mapName)
        {
            MemoryMappedFile memMap = null;
            try
            {
                memMap = MemoryMappedFile.OpenExisting(mapName);
            }
            catch (FileNotFoundException ex)
            {
                if (ex.Message != "Unable to find the specified file.")
                {
                    //BIG ERROR, report it
                    System.Diagnostics.Debug.WriteLine("Error " + ex.Message);
                }
                memMap = null;
            }
            //Create the memory map if needed
            try
            {
                if (memMap == null)
                    memMap = MemoryMappedFile.CreateNew(mapName, 10000);
            }
            catch (Exception ex)
            {
                //BIG ERROR, report it
                System.Diagnostics.Debug.WriteLine("Error " + ex.Message);
                memMap = null;
            }
            return memMap;
        }
        private int PacketSize()
        {
            UpdateInfoPacket packet = new UpdateInfoPacket();
            int size = Marshal.SizeOf(packet);
            return size;
        }
        private byte[] PacketToBytes(UpdateInfoPacket packet)
        {
            int size = Marshal.SizeOf(packet);
            byte[] array = new byte[size];
            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(packet, ptr, true);
            Marshal.Copy(ptr, array, 0, size);
            Marshal.FreeHGlobal(ptr);
            return array;
        }
        private UpdateInfoPacket BytesToPacket(byte[] packet)
        {
            UpdateInfoPacket structure = new UpdateInfoPacket();
            int size = Marshal.SizeOf(structure);
            IntPtr ptr = Marshal.AllocHGlobal(size);
            Marshal.Copy(packet, 0, ptr, size);
            structure = (UpdateInfoPacket)Marshal.PtrToStructure(ptr, structure.GetType());
            Marshal.FreeHGlobal(ptr);
            return structure;
        }
        private void ReadMemoryMap(out UpdateInfoPacket packet)
        {
            packet = new UpdateInfoPacket();
            MemoryMappedViewStream memStream = null;
            try
            {
                //Make sure there is a map first
                if (m_memMap == null) return;
                //Create the view stream
                memStream = m_memMap.CreateViewStream();
                memStream.Seek(0, SeekOrigin.Begin);
                //Create the object to read from the memory map
                using (BinaryReader reader = new BinaryReader(memStream))
                {
                    //Read the data from memory in bytes
                    byte[] rawPacket = reader.ReadBytes(PacketSize());
                    //Convert the byte data to the structure
                    if (rawPacket != null) packet = BytesToPacket(rawPacket);
                }
            }
            catch (Exception ex)
            {
                //BIG ERROR, report it
                System.Diagnostics.Debug.WriteLine("Error " + ex.Message);
            }
        }
        private void WriteMemoryMap(UpdateInfoPacket packet)
        {
            MemoryMappedViewStream memStream = null;
            try
            {
                //Make sure there is a map first
                if (m_memMap == null) return;
                //Create the view stream
                memStream = m_memMap.CreateViewStream();
                memStream.Seek(0, SeekOrigin.Begin);
                //Create the object to write to the memory map
                using (BinaryWriter writer = new BinaryWriter(memStream))
                {
                    //Convert the structure to a byte array
                    byte[] rawPacket = PacketToBytes(packet);
                    //Write the byte array to memory
                    writer.Write(rawPacket);
                }
            }
            catch (Exception ex)
            {
                //BIG ERROR, report it
                System.Diagnostics.Debug.WriteLine("Error " + ex.Message);
            }
        }
    }
}