C# 内存映射文件,应用挂起。怎么了?
C# Memory Mapped Files, app is hang on. What's wrong?
我正在尝试为带有内存映射文件的 IPC 编写简单的 sender/receiver class。
所以我的代码有问题,但我不明白我在这里做错了什么:
[Serializable]
public struct MessageData
{
public int PID;
public IntPtr HWND;
public string ProcessName;
public string ProcessTitle;
}
....
public static class MMF
{
private const int MMF_MAX_SIZE = 4096; // allocated memory for this memory mapped file (bytes)
private const int MMF_VIEW_SIZE = 4096; // how many bytes of the allocated memory can this process access
public static void Write()
{
var security = new MemoryMappedFileSecurity();
// Create a SecurityIdentifier object for "everyone".
SecurityIdentifier everyoneSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new AccessRule<MemoryMappedFileRights>(everyoneSid, MemoryMappedFileRights.FullControl, AccessControlType.Allow));
using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("Global\mmf1", MMF_MAX_SIZE, MemoryMappedFileAccess.ReadWrite))
{
using (MemoryMappedViewStream mStream = mmf.CreateViewStream(0, MMF_VIEW_SIZE))
{
var p = Process.GetCurrentProcess();
MessageData msgData = new MessageData();
msgData.HWND = p.MainWindowHandle;
msgData.PID = p.Id;
msgData.ProcessName = p.ProcessName;
msgData.ProcessTitle = p.MainWindowTitle;
// serialize the msgData and write it to the memory mapped file
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(mStream, msgData);
mStream.Flush();
mStream.Seek(0, SeekOrigin.Begin); // sets the current position back to the beginning of the stream
//MessageBox.Show("Done");
}
}
}
}
现在我尝试从主应用程序表单测试此代码:
...
private void button1_Click(object sender, EventArgs e)
{
MMF.Write();
}
并在 Visual Studio 2015 社区中进行处理。处理 运行,但表单界面没有响应。我只能暂停或停止进程。这在 using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("Global\mmf1", ...
字符串上停止。
我假设应用程序无法创建文件,但没有任何例外。
因此,如果我将地图名称更改为 "mmf1"(没有 "Global" 前缀)一切正常,应用程序运行正常。但据我所知 this answer and MSDN:
Prefixing the file mapping object names with "Global\" allows processes to communicate with each other even if they are in different terminal server sessions.
如果我理解正确,需要前缀 "Global\" 才能将我的内存映射文件与任何应用程序交互,无论它们 运行ning 的权限如何。
特别是因为我正在尝试为 "everyone" 设置文件访问权限。
UPD. 此代码在 Win 7 / Win 8.1 x64 上测试。结果是一样的。
您必须 运行 Visual Studio 作为管理员才能使用 "Global\" 前缀创建内存映射文件。
我正在尝试为带有内存映射文件的 IPC 编写简单的 sender/receiver class。 所以我的代码有问题,但我不明白我在这里做错了什么:
[Serializable]
public struct MessageData
{
public int PID;
public IntPtr HWND;
public string ProcessName;
public string ProcessTitle;
}
....
public static class MMF
{
private const int MMF_MAX_SIZE = 4096; // allocated memory for this memory mapped file (bytes)
private const int MMF_VIEW_SIZE = 4096; // how many bytes of the allocated memory can this process access
public static void Write()
{
var security = new MemoryMappedFileSecurity();
// Create a SecurityIdentifier object for "everyone".
SecurityIdentifier everyoneSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new AccessRule<MemoryMappedFileRights>(everyoneSid, MemoryMappedFileRights.FullControl, AccessControlType.Allow));
using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("Global\mmf1", MMF_MAX_SIZE, MemoryMappedFileAccess.ReadWrite))
{
using (MemoryMappedViewStream mStream = mmf.CreateViewStream(0, MMF_VIEW_SIZE))
{
var p = Process.GetCurrentProcess();
MessageData msgData = new MessageData();
msgData.HWND = p.MainWindowHandle;
msgData.PID = p.Id;
msgData.ProcessName = p.ProcessName;
msgData.ProcessTitle = p.MainWindowTitle;
// serialize the msgData and write it to the memory mapped file
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(mStream, msgData);
mStream.Flush();
mStream.Seek(0, SeekOrigin.Begin); // sets the current position back to the beginning of the stream
//MessageBox.Show("Done");
}
}
}
}
现在我尝试从主应用程序表单测试此代码:
...
private void button1_Click(object sender, EventArgs e)
{
MMF.Write();
}
并在 Visual Studio 2015 社区中进行处理。处理 运行,但表单界面没有响应。我只能暂停或停止进程。这在 using (MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("Global\mmf1", ...
字符串上停止。
我假设应用程序无法创建文件,但没有任何例外。
因此,如果我将地图名称更改为 "mmf1"(没有 "Global" 前缀)一切正常,应用程序运行正常。但据我所知 this answer and MSDN:
Prefixing the file mapping object names with "Global\" allows processes to communicate with each other even if they are in different terminal server sessions.
如果我理解正确,需要前缀 "Global\" 才能将我的内存映射文件与任何应用程序交互,无论它们 运行ning 的权限如何。
特别是因为我正在尝试为 "everyone" 设置文件访问权限。
UPD. 此代码在 Win 7 / Win 8.1 x64 上测试。结果是一样的。
您必须 运行 Visual Studio 作为管理员才能使用 "Global\" 前缀创建内存映射文件。