繁体   English   中英

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

[英]How do I use memory sharing correctly in c#.Net 4?

我不知道这是由于过时的帖子还是仅仅是由于缺乏理解,但是在使用.Net4中的内存映射时,我似乎遇到了各种各样的错误信息。 也许.Net4在Beta中发布后,每个人都开始发布它,而.Net4 beta中的情况有所不同吗? 或者,也许我只是不知道我在说什么,它们还不错,但是我似乎无法弄清楚使用内存映射的正确方法。 我正在寻找一种在两个应用程序上使用相同代码的方法,因此该代码是通用的,并且两个应用程序之一将不被视为主要代码(这会创建其他应用程序需要的东西)。 示例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
            }
        }
    }
}

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM