|
本帖最后由 shiy720 于 2025-3-6 23:33 编辑
在C#中,实现多个程序之间的内存共享和消息循环可以通过 内存映射文件(Memory-Mapped Files) 结合 事件(Event) 或 信号量(Semaphore) 来实现。以下是一个完整的示例,展示如何实现多个程序之间的内存共享和消息循环。
我们可以将共享内存和消息循环的逻辑封装到一个单独的 `SharedMemoryMessageQueue` 类中,以便更好地复用和管理代码。以下是一个完整的实现:
### 封装后的消息类
- using System;
- using System.IO.MemoryMappedFiles;
- using System.Text;
- using System.Text.Json;
- using System.Threading;
- public class SharedMemoryMessageQueue : IDisposable
- {
- private const int BufferSize = 1024; // 共享内存缓冲区大小
- private const string DefaultMapName = "SharedMemoryMap";
- private const string DefaultEventName = "SharedMemoryEvent";
- private readonly string _mapName;
- private readonly string _eventName;
- private readonly MemoryMappedFile _mmf;
- private readonly EventWaitHandle _eventHandle;
- public SharedMemoryMessageQueue(string mapName = DefaultMapName, string eventName = DefaultEventName)
- {
- _mapName = mapName;
- _eventName = eventName;
- // 创建或打开内存映射文件
- _mmf = MemoryMappedFile.CreateOrOpen(_mapName, BufferSize);
- // 创建或打开事件
- _eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, _eventName);
- }
- /// <summary>
- /// 发送消息到共享内存
- /// </summary>
- public void SendMessage<T>(T message)
- {
- // 序列化消息
- string json = JsonSerializer.Serialize(message);
- byte[] buffer = Encoding.UTF8.GetBytes(json);
- if (buffer.Length > BufferSize - sizeof(int))
- {
- throw new InvalidOperationException("Message is too large for the shared memory buffer.");
- }
- // 写入共享内存
- using (var accessor = _mmf.CreateViewAccessor())
- {
- accessor.Write(0, buffer.Length); // 写入消息长度
- accessor.WriteArray(sizeof(int), buffer, 0, buffer.Length); // 写入消息内容
- }
- // 通知接收方
- _eventHandle.Set();
- }
- /// <summary>
- /// 从共享内存接收消息
- /// </summary>
- public T ReceiveMessage<T>()
- {
- // 等待发送方的通知
- _eventHandle.WaitOne();
- // 读取共享内存
- using (var accessor = _mmf.CreateViewAccessor())
- {
- int length = accessor.ReadInt32(0); // 读取消息长度
- byte[] buffer = new byte[length];
- accessor.ReadArray(sizeof(int), buffer, 0, length); // 读取消息内容
- // 反序列化消息
- string json = Encoding.UTF8.GetString(buffer);
- return JsonSerializer.Deserialize<T>(json);
- }
- }
- /// <summary>
- /// 释放资源
- /// </summary>
- public void Dispose()
- {
- _mmf?.Dispose();
- _eventHandle?.Dispose();
- }
- }
复制代码
### 使用示例
#### 发送消息的程序(Producer)
- using System;
- class Producer
- {
- static void Main()
- {
- using (var messageQueue = new SharedMemoryMessageQueue())
- {
- while (true)
- {
- Console.WriteLine("Enter a message (or 'exit' to quit):");
- string input = Console.ReadLine();
- if (input.ToLower() == "exit")
- break;
- // 发送消息
- var message = new { Sender = "Producer", Content = input, Timestamp = DateTime.UtcNow };
- messageQueue.SendMessage(message);
- Console.WriteLine("Message sent.");
- }
- }
- }
- }
复制代码
#### 接收消息的程序(Consumer)
- using System;
- class Consumer
- {
- static void Main()
- {
- using (var messageQueue = new SharedMemoryMessageQueue())
- {
- while (true)
- {
- Console.WriteLine("Waiting for a message...");
- // 接收消息
- var message = messageQueue.ReceiveMessage<SharedMessage>();
- Console.WriteLine($"Received message from {message.Sender} at {message.Timestamp}: {message.Content}");
- }
- }
- }
- }
- // 定义消息格式
- public class SharedMessage
- {
- public string Sender { get; set; }
- public string Content { get; set; }
- public DateTime Timestamp { get; set; }
- }
复制代码
### 运行步骤
1. 启动 **Consumer** 程序,它会等待消息。
2. 启动 **Producer** 程序,输入消息并发送。
3. **Consumer** 程序会接收到消息并显示。
### 关键点
1. **封装共享内存和事件**:将共享内存和事件的逻辑封装到 `SharedMemoryMessageQueue` 类中,简化了使用。
2. **泛型支持**:`SendMessage` 和 `ReceiveMessage` 方法支持泛型,可以发送和接收任意类型的消息。
3. **资源管理**:实现了 `IDisposable` 接口,确保共享内存和事件句柄的正确释放。
4. **线程安全**:通过事件实现了进程间的同步,确保消息的正确传递。
### 扩展功能
- **超时机制**:可以为 `ReceiveMessage` 方法添加超时参数,避免无限等待。
- **错误处理**:增加对共享内存和事件的错误处理,确保程序的健壮性。
- **多消费者**:可以使用多个事件或信号量来实现多个消费者。
### 总结
通过封装共享内存和事件逻辑,我们实现了一个简单且易用的消息队列类 `SharedMemoryMessageQueue`。它可以用于多个程序之间的高效通信,适用于需要高性能和低延迟的场景。
|
|