我使用MemoryMappedFile
做了一个简单的测试msdn说:
2个进程,1个内存映射文件:
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();
}
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”在哪里?
但是,如果我第一个进程 ONLY (没有激活进程B),我会得到:
我错过了什么?
我希望看到:
Process A says: 1
Process B says: 2
答案 0 :(得分:7)
您正在与BinaryWriter.Write(字符串)的实现细节作斗争。它首先写入字符串的长度,以便BinaryReader知道在读回字符串时需要读取的字符数。对于短字符串,如“1”,它会写一个字节来存储长度。
因此,传递给CreateViewStream()的偏移量是错误的,传递1将使覆盖部分由进程A写入的字符串。您看到的笑脸字符是(char)1的字形。进程B写入的字符串的长度字节。
内存映射文件在托管代码中很麻烦。您通常通过声明一个结构来设置布局并使用指针访问视图但是需要不安全的代码来读取和写入它们。 Streams对于一大块记忆来说是一个相当糟糕的抽象,但却是一种必要的邪恶。这也是MMF在.NET中可用的原因。
答案 1 :(得分:0)
编辑
我注意到ProcessB
的代码中有一个显然很奇怪的东西。这段代码
using (MemoryMappedViewStream stream = mmf.CreateViewStream(1, 0))
从第一个字节创建一个视图,但.NET
中的字符串是2个字节。我认为你应该让1->2
成为2.所以ProcessB
视图从映射文件开头的偏移量将在已经插入之后来自ProcessA
的1“字符串。
在你的情况下似乎你重叠。
希望这有帮助。