找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 6|回复: 0

[工具类] 在C#中,实现多个程序之间的内存共享

[复制链接]
发表于 6 天前 | 显示全部楼层 |阅读模式
本帖最后由 shiy720 于 2025-3-6 23:33 编辑

在C#中,实现多个程序之间的内存共享和消息循环可以通过 内存映射文件(Memory-Mapped Files) 结合 事件(Event) 或 信号量(Semaphore) 来实现。以下是一个完整的示例,展示如何实现多个程序之间的内存共享和消息循环。
我们可以将共享内存和消息循环的逻辑封装到一个单独的 `SharedMemoryMessageQueue` 类中,以便更好地复用和管理代码。以下是一个完整的实现:

### 封装后的消息类
  1. using System;
  2. using System.IO.MemoryMappedFiles;
  3. using System.Text;
  4. using System.Text.Json;
  5. using System.Threading;

  6. public class SharedMemoryMessageQueue : IDisposable
  7. {
  8.     private const int BufferSize = 1024; // 共享内存缓冲区大小
  9.     private const string DefaultMapName = "SharedMemoryMap";
  10.     private const string DefaultEventName = "SharedMemoryEvent";

  11.     private readonly string _mapName;
  12.     private readonly string _eventName;
  13.     private readonly MemoryMappedFile _mmf;
  14.     private readonly EventWaitHandle _eventHandle;

  15.     public SharedMemoryMessageQueue(string mapName = DefaultMapName, string eventName = DefaultEventName)
  16.     {
  17.         _mapName = mapName;
  18.         _eventName = eventName;

  19.         // 创建或打开内存映射文件
  20.         _mmf = MemoryMappedFile.CreateOrOpen(_mapName, BufferSize);

  21.         // 创建或打开事件
  22.         _eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, _eventName);
  23.     }

  24.     /// <summary>
  25.     /// 发送消息到共享内存
  26.     /// </summary>
  27.     public void SendMessage<T>(T message)
  28.     {
  29.         // 序列化消息
  30.         string json = JsonSerializer.Serialize(message);
  31.         byte[] buffer = Encoding.UTF8.GetBytes(json);

  32.         if (buffer.Length > BufferSize - sizeof(int))
  33.         {
  34.             throw new InvalidOperationException("Message is too large for the shared memory buffer.");
  35.         }

  36.         // 写入共享内存
  37.         using (var accessor = _mmf.CreateViewAccessor())
  38.         {
  39.             accessor.Write(0, buffer.Length); // 写入消息长度
  40.             accessor.WriteArray(sizeof(int), buffer, 0, buffer.Length); // 写入消息内容
  41.         }

  42.         // 通知接收方
  43.         _eventHandle.Set();
  44.     }

  45.     /// <summary>
  46.     /// 从共享内存接收消息
  47.     /// </summary>
  48.     public T ReceiveMessage<T>()
  49.     {
  50.         // 等待发送方的通知
  51.         _eventHandle.WaitOne();

  52.         // 读取共享内存
  53.         using (var accessor = _mmf.CreateViewAccessor())
  54.         {
  55.             int length = accessor.ReadInt32(0); // 读取消息长度
  56.             byte[] buffer = new byte[length];
  57.             accessor.ReadArray(sizeof(int), buffer, 0, length); // 读取消息内容

  58.             // 反序列化消息
  59.             string json = Encoding.UTF8.GetString(buffer);
  60.             return JsonSerializer.Deserialize<T>(json);
  61.         }
  62.     }

  63.     /// <summary>
  64.     /// 释放资源
  65.     /// </summary>
  66.     public void Dispose()
  67.     {
  68.         _mmf?.Dispose();
  69.         _eventHandle?.Dispose();
  70.     }
  71. }
复制代码


### 使用示例

#### 发送消息的程序(Producer)
  1. using System;

  2. class Producer
  3. {
  4.     static void Main()
  5.     {
  6.         using (var messageQueue = new SharedMemoryMessageQueue())
  7.         {
  8.             while (true)
  9.             {
  10.                 Console.WriteLine("Enter a message (or 'exit' to quit):");
  11.                 string input = Console.ReadLine();

  12.                 if (input.ToLower() == "exit")
  13.                     break;

  14.                 // 发送消息
  15.                 var message = new { Sender = "Producer", Content = input, Timestamp = DateTime.UtcNow };
  16.                 messageQueue.SendMessage(message);
  17.                 Console.WriteLine("Message sent.");
  18.             }
  19.         }
  20.     }
  21. }
复制代码

#### 接收消息的程序(Consumer)
  1. using System;

  2. class Consumer
  3. {
  4.     static void Main()
  5.     {
  6.         using (var messageQueue = new SharedMemoryMessageQueue())
  7.         {
  8.             while (true)
  9.             {
  10.                 Console.WriteLine("Waiting for a message...");

  11.                 // 接收消息
  12.                 var message = messageQueue.ReceiveMessage<SharedMessage>();
  13.                 Console.WriteLine($"Received message from {message.Sender} at {message.Timestamp}: {message.Content}");
  14.             }
  15.         }
  16.     }
  17. }

  18. // 定义消息格式
  19. public class SharedMessage
  20. {
  21.     public string Sender { get; set; }
  22.     public string Content { get; set; }
  23.     public DateTime Timestamp { get; set; }
  24. }
复制代码

### 运行步骤
1. 启动 **Consumer** 程序,它会等待消息。
2. 启动 **Producer** 程序,输入消息并发送。
3. **Consumer** 程序会接收到消息并显示。

### 关键点
1. **封装共享内存和事件**:将共享内存和事件的逻辑封装到 `SharedMemoryMessageQueue` 类中,简化了使用。
2. **泛型支持**:`SendMessage` 和 `ReceiveMessage` 方法支持泛型,可以发送和接收任意类型的消息。
3. **资源管理**:实现了 `IDisposable` 接口,确保共享内存和事件句柄的正确释放。
4. **线程安全**:通过事件实现了进程间的同步,确保消息的正确传递。

### 扩展功能
- **超时机制**:可以为 `ReceiveMessage` 方法添加超时参数,避免无限等待。
- **错误处理**:增加对共享内存和事件的错误处理,确保程序的健壮性。
- **多消费者**:可以使用多个事件或信号量来实现多个消费者。

### 总结
通过封装共享内存和事件逻辑,我们实现了一个简单且易用的消息队列类 `SharedMemoryMessageQueue`。它可以用于多个程序之间的高效通信,适用于需要高性能和低延迟的场景。


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|西兴社区 ( 蜀ICP备2022005627号 )|网站地图

GMT+8, 2025-3-12 19:23 , Processed in 0.153033 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表