MemoryMappedFile不适用于2个进程?
我用MemoryMappedFile
做了一个简单的测试,因为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(); }
过程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(); }
结果是:
胡?
“1”,“2”在哪里?
但是,如果我只运行第一个进程(没有激活进程B),我得到:
我错过了什么?
我希望看到:
Process A says: 1 Process B says: 2
您正在与BinaryWriter.Write(字符串)的实现细节作斗争。 它首先写入字符串的长度,以便BinaryReader知道在读回字符串时需要读取多少字符。 对于短字符串,如“1”,它会写入一个字节来存储长度。
因此传递给CreateViewStream()的偏移量是错误的,传递1会使它覆盖进程A写入的字符串的一部分。您看到的笑脸字符是(char)1的字形。 进程B写入的字符串的长度字节。
内存映射文件在托管代码中很麻烦。 您通常通过声明一个结构来设置布局并使用指针来访问视图但是需要不安全的代码来读取和写入它们。 Streams对于一大块记忆来说是一个相当糟糕的抽象,但却是一种必要的邪恶。 也是MMF在.NET中使用这么长时间的原因。
编辑
我注意到ProcessB
的代码中有一个显然很奇怪的东西。 这段代码
using (MemoryMappedViewStream stream = mmf.CreateViewStream(1, 0))
从第一个字节创建一个视图,但.NET
中的字符串是2个字节。 我认为你应该让1->2
成为2.所以ProcessB
视图从映射文件的开头的偏移量将在已经从ProcessA
插入“1”字符串之后。
在你的情况下似乎你重叠他们。
希望这可以帮助。
- DirectoryInfo.EnumerateFiles(…)导致UnauthorizedAccessException(和其他exception)
- 我可以为此方案设计任何无锁解决方案
- C#to VB.NET语法转换,用于具有属性的类实例化
- 传递运行时类型时无法解决符号exception
- 为异步执行排队操作/代理
- File.ReadLines何时释放资源
- 检查我的WPF WebBrowser中的元素,使用“inspect element(s)”(IE,Chrome,Firefox)获取css路径(“copy css-path”)
- 从WCF客户端连接到服务器的问题 – HTTPS端点 – 适用于本地开发但不适用于服务器
- 使用类名和方法名调用类的成员