【问题标题】:How do I use memory sharing correctly in c#.Net 4?如何在 c#.Net 4 中正确使用内存共享?
【发布时间】:2016-03-01 22:05:49
【问题描述】:

我不知道是因为旧帖子还是缺乏理解,但在 .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
            }
        }
    }
}

【问题讨论】:

  • 您是否担心特定的事情?
  • 嗯,我很确定这些例子现在完全错了。我只是希望有人用代码回答我可以在 app1.exe 和 app2.exe 中放置什么 sn-p 来表示,共享我制作的结构。我需要如何确定所需的内存量,我需要如何打开内存映射文件(我可以只使用 CreateOrOpen 而不是使用 CreateFromFile)等等。但我现在只想有人给我看一个例子, 2016 年。;)
  • 这些示例不能满足您的需要,但我不会称它们为大错特错。即使我不知道“重载是错误的”,修复它也不应该太难。如果没有更多关于您想要实现的目标的上下文,很难回答。这应该成为一种IP机制吗?也许使用命名管道。
  • 当我说"These examples are dead wrong" 这意味着它们根本不正确并且不会编译。我 100% 告诉你示例中使用的重载是不正确的。我不明白回答我的问题有什么难的。我只是想要一个示例,说明如何以非常特定的方式在两个应用程序之间正确使用内存共享。我想我已经很清楚地说明了我想要得到的答案。无论如何,这一切都没有实际意义,我刚刚发布了一个我想出的答案,只是尝试了不同的事情并进行了更多的研究。感谢 cmets。
  • Stack Overflow 不是编码服务。最好的问题是关于具体问题。在不清楚 OP 不清楚的地方提供示例代码并不是大多数人愿意做的事情(因为它很无聊并且经常错过问题的重点)。

标签: c# memory .net-4.0 memory-mapped-files memory-mapping


【解决方案1】:

在其他地方进行了大量研究之后,试图清除多年来不正确的旧代码(早在 .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);
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2015-05-29
    • 2011-05-27
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    相关资源
    最近更新 更多