MemoryMappedFile不适用于2个进程?

Roy*_*mir 2 c# .net-4.0 memory-mapped-files

我用MemoryMappedFileas msdn做了一个简单的测试:

2个进程,1个内存映射文件:

  • 第一个进程添加字符串"1"
  • 第一个进程等待
  • 第二个进程添加字符串"2"并终止
  • 第一个进程现在读取整个内存映射文件

过程A:

using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000))
            {
                bool mutexCreated;
                Mutex mutex = new Mutex(true, "testmapmutex", out mutexCreated);
                using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                {
                    BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);
                    writer.Write("1");
                }
                mutex.ReleaseMutex();
                Console.WriteLine("Start Process B and press ENTER to continue.");
                Console.ReadLine();
                mutex.WaitOne();
                using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                {
                    BinaryReader reader = new BinaryReader(stream, Encoding.UTF8);
                    Console.WriteLine("Process A says: {0}", reader.ReadString());
                    Console.WriteLine("Process B says: {0}", reader.ReadString());
                }
                mutex.ReleaseMutex();
            }
Run Code Online (Sandbox Code Playgroud)

过程B:

 using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))
                {
                    Mutex mutex = Mutex.OpenExisting("testmapmutex");
                    mutex.WaitOne();
                    using (MemoryMappedViewStream stream = mmf.CreateViewStream(1, 0))
                    {
                        BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8);
                        writer.Write("2");
                    }
                    mutex.ReleaseMutex();
                }
Run Code Online (Sandbox Code Playgroud)

结果是:

在此输入图像描述

胡?

"1","2"在哪里?

但是,如果我运行第一个进程(没有激活进程B),我得到:

在此输入图像描述

我错过了什么?

我希望看到:

Process A says: 1
Process B says: 2
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 7

您正在与BinaryWriter.Write(字符串)的实现细节作斗争.它首先写入字符串的长度,以便BinaryReader知道在读回字符串时需要读取多少个字符.对于短字符串,如"1",它会写入一个字节来存储长度.

因此传递给CreateViewStream()的偏移量是错误的,传递1会使它覆盖进程A写入的字符串的一部分.您看到的笑脸字符是(char)1的字形.进程B写入的字符串的长度字节.

内存映射文件在托管代码中很麻烦.您通常通过声明一个结构来设置布局并使用指针访问视图但是需要不安全的代码来读取和写入它们.Streams对于一大块记忆来说是一个相当糟糕的抽象,但却是一种必要的邪恶.这也是MMF在.NET中使用这么长时间的原因.