想要在两个程序之间通讯,A写入,B读取,询问豆包,给出答案,参考并改进为如下
创建共享内存类
首先,创建一个用于处理共享内存操作的类。在这个类中,将使用 System.IO.MemoryMappedFiles 命名空间下的相关类来实现共享内存功能。
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices;
class SharedMemoryIPC
{
private const string SharedMemoryName = "MySharedMemory";
private const int SharedMemorySize = 1024;
private MemoryMappedFile _memoryMappedFile;
private MemoryMappedViewAccessor _viewAccessor;
public bool OpenSharedMemory()
{
try
{
_memoryMappedFile = MemoryMappedFile.CreateOrOpen(SharedMemoryName, SharedMemorySize, MemoryMappedFileAccess.ReadWrite);
_viewAccessor = _memoryMappedFile.CreateViewAccessor();
return true;
}
catch (Exception ex)
{
Console.WriteLine($"共享内存打开失败: {ex.Message}");
return false;
}
}
public bool WriteToSharedMemory(string data)
{
try
{
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(data);
if (buffer.Length <= SharedMemorySize)
{
_viewAccessor.WriteArray(0, buffer, 0, buffer.Length);
return true;
}
else
{
Console.WriteLine("写入数据过长,超过共享内存大小");
return false;
}
}
catch (Exception ex)
{
Console.WriteLine($"数据写入共享内存失败: {ex.Message}");
return false;
}
}
public string ReadFromSharedMemory()
{
try
{
byte[] buffer = new byte[SharedMemorySize];
_viewAccessor.ReadArray(0, buffer, 0, SharedMemorySize);
return System.Text.Encoding.UTF8.GetString(buffer).TrimEnd('\0');
}
catch (Exception ex)
{
Console.WriteLine($"从共享内存读取数据失败: {ex.Message}");
return "";
}
}
public void CloseSharedMemory()
{
if (_viewAccessor!= null)
{
_viewAccessor.Dispose();
}
if (_memoryMappedFile!= null)
{
_memoryMappedFile.Dispose();
}
}
}
在上述类中:
- SharedMemoryName 定义了共享内存的名称,不同进程通过这个相同的名称来访问同一共享内存段。
- SharedMemorySize 设定了共享内存的大小,这里设置为 1024 字节。
- OpenSharedMemory 方法用于创建或打开共享内存段,并创建访问器以便后续对共享内存进行读写操作。
- WriteToSharedMemory 方法将传入的字符串数据转换为字节数组后写入共享内存。
- ReadFromSharedMemory 方法从共享内存中读取数据并转换为字符串返回。
- CloseSharedMemory 方法用于关闭共享内存视图访问器和共享内存文件映射对象,释放相关资源。
新建一个写入程序
public partial class WriteFrm : Form
{
public WriteFrm()
{
InitializeComponent();
}
SharedMemoryIPC sharedMemory;
bool isOpen = false;
private void Form1_Load(object sender, EventArgs e)
{
sharedMemory = new SharedMemoryIPC();
isOpen = sharedMemory.OpenSharedMemory();
}
private void button1_Click(object sender, EventArgs e)
{
if (isOpen)
{
string dataToWrite = textBox1.Text;
if (sharedMemory.WriteToSharedMemory(dataToWrite))
{
Console.WriteLine($"数据已成功写入共享内存: {dataToWrite}");
}
else
{
Console.WriteLine("数据写入共享内存失败");
}
}
}
private void WriteFrm_FormClosing(object sender, FormClosingEventArgs e)
{
sharedMemory.CloseSharedMemory();
}
}
读取程序
public partial class ReadFrm : Form
{
public ReadFrm()
{
InitializeComponent();
}
SharedMemoryIPC sharedMemory;
bool isOpen = false;
private void ReadFrm_Load(object sender, EventArgs e)
{
sharedMemory = new SharedMemoryIPC();
isOpen = sharedMemory.OpenSharedMemory();
}
private void button1_Click(object sender, EventArgs e)
{
if (isOpen)
{
string dataRead = sharedMemory.ReadFromSharedMemory();
Console.WriteLine($"从共享内存读取的数据: {dataRead}");
textBox1.Text = dataRead;
}
}
private void ReadFrm_FormClosing(object sender, FormClosingEventArgs e)
{
sharedMemory.CloseSharedMemory();
}
}
问题点
数据以覆盖方式写入,当第一次写入的数据长度较长,二次写入的较短时,读取数据会发现读到的有上次的数据部分
public bool ClearSharedMemoryData()
{
try
{
byte[] zeroBuffer = new byte[SharedMemorySize];
_viewAccessor.WriteArray(0, zeroBuffer, 0, SharedMemorySize);
return true;
}
catch (Exception ex)
{
Console.WriteLine($"清空共享内存数据失败: {ex.Message}");
return false;
}
}
ClearSharedMemoryData方法创建了一个大小与共享内存相同的字节数组zeroBuffer,数组中的所有元素初始化为 0。然后使用WriteArray方法将这个字节数组写入共享内存视图访问器,从偏移量 0 开始,写入的长度为共享内存的大小SharedMemorySize,这样就将共享内存中的所有数据都设置为 0,实现了清空数据的目的。对于更复杂的情况,要根据具体情况,进行清除。