MemoryMappedFile不与2原有的工作流程?有的、不与、工作流程、MemoryMappedFile

2023-09-08 09:02:15 作者:很酷的殺手

我做了一个 MemoryMappedFile 一个简单的测试,为的 MSDN 说:

2的过程,1内存映射文件:

第一过程添加字符串1 的第一道工序等待 第二处理将字符串2和终止 的第一道工序,现在读取整个内存映射文件

程序 - 答:

 使用(MemoryMappedFile MMF = MemoryMappedFile.CreateNew(testmap,10000))
            {
                布尔mutexCreated;
                互斥互斥=新的mutex(真的,testmapmutex,出mutexCreated);
                使用(MemoryMappedViewStream流= mmf.CreateViewStream())
                {
                    的BinaryWriter作家=新的BinaryWriter(流Encoding.UTF8);
                    writer.Write(1);
                }
                mutex.ReleaseMutex();
                Console.WriteLine(启动进程B和preSS回车键继续。);
                到Console.ReadLine();
                mutex.WaitOne();
                使用(MemoryMappedViewStream流= mmf.CreateViewStream())
                {
                    读者BinaryReader在新= BinaryReader在(流Encoding.UTF8);
                    Console.WriteLine(的处理的说:{0},reader.ReadString());
                    Console.WriteLine(方法B说:{0},reader.ReadString());
                }
                mutex.ReleaseMutex();
            }
 

进程B:

 使用(MemoryMappedFile MMF = MemoryMappedFile.OpenExisting(testmap))
                {
                    互斥互斥= Mutex.OpenExisting(testmapmutex);
                    mutex.WaitOne();
                    使用(MemoryMappedViewStream流= mmf.CreateViewStream(1,0))
                    {
                        的BinaryWriter作家=新的BinaryWriter(流Encoding.UTF8);
                        writer.Write(2);
                    }
                    mutex.ReleaseMutex();
                }
 

结果是:

胡?

哪里是1,2?

不过,如果我跑的仅的第一道工序(无需激活过程中B)我得到:

我在想什么?

我希望看到:

 进程A说:1
方法B说:2
 
想做出纳又啥都不会 工作流程 15笔业务处理,真是专属我的福利

解决方案

正在争夺BinaryWriter.Write(串)的实现细节。它写入字符串的长度第一,需要让知道BinaryReader在多少个字符,它需要读回字符串时阅读。为短字符串,如1,将其写入一个字节来存储长度

所以偏移传递给CreateViewStream()是错误的,经过1将使它的覆盖的写的过程A.您所看到的笑脸字符的字符串的一部分是字形(字符)1 。字符串的长度字节写的进程B。

内存映射文件的麻烦,在管理code。通常你阅读和声明一个结构来设置布局,并使用指针访问视图写信给他们,但是这需要不安全code。流是pretty的穷人抽象的内存块,但必要之恶。此外,它花了这么长的时间货币市场基金之所以成为.NET中可用。

I've made a simple test with a MemoryMappedFile as msdn says :

2 processes, 1 memory mapped file :

the first process adds the string "1" the first process waits the second process adds the string "2" and terminates the first process now reads the whole memory mapped file

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

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

The result is :

Hu ?

Where is "1", "2" ?

However, if I run ONLY the first process ( without activating process B) I get :

What am I missing ?

I expect to see :

Process A says: 1
Process B says: 2

解决方案

You are battling an implementation detail of BinaryWriter.Write(string). It writes the length of the string first, required so that BinaryReader knows how many characters it needs to read when reading the string back. For short strings, like "1", it writes a single byte to store the length.

So the offset you pass to CreateViewStream() is wrong, passing 1 will make it overwrite part of the string written by process A. The smiley character you see is the glyph for (char)1. The length byte of the string written by process B.

Memory mapped files are troublesome in managed code. You normally read and write to them by declaring a struct to set the layout and using pointers to access the view but that requires unsafe code. Streams are a pretty poor abstraction for a chunk of memory but a necessary evil. Also the reason it took so long for MMFs to become available in .NET.