shiy720 发表于 2025-3-6 23:31:40

在C#中,实现多个程序之间的内存共享

本帖最后由 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;
            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`。它可以用于多个程序之间的高效通信,适用于需要高性能和低延迟的场景。


页: [1]
查看完整版本: 在C#中,实现多个程序之间的内存共享