C# 多窗口通信实现方案
几种 C# 多窗口通信的完整实现方案,包括事件机制、消息传递、服务定位等模式。
方案一:基于事件/委托的通信 (推荐)
1. 基础事件通信模式
// EventCommunication.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
// 1. 定义消息类
public class WindowMessage
{
public string Sender { get; set; }
public string Receiver { get; set; }
public string MessageType { get; set; }
public object Data { get; set; }
public DateTime Timestamp { get; set; }
public WindowMessage(string sender, string receiver, string type, object data)
{
Sender = sender;
Receiver = receiver;
MessageType = type;
Data = data;
Timestamp = DateTime.Now;
}
}
// 2. 事件管理器(单例模式)
public class WindowEventManager
{
private static WindowEventManager _instance;
private static readonly object _lock = new object();
// 定义事件委托
public delegate void MessageReceivedHandler(WindowMessage message);
// 全局消息事件
public event MessageReceivedHandler GlobalMessageReceived;
// 窗口特定消息字典
private Dictionary<string, MessageReceivedHandler> _windowHandlers;
private WindowEventManager()
{
_windowHandlers = new Dictionary<string, MessageReceivedHandler>();
}
public static WindowEventManager Instance
{
get
{
lock (_lock)
{
return _instance ?? (_instance = new WindowEventManager());
}
}
}
// 注册窗口消息处理器
public void RegisterWindow(string windowName, MessageReceivedHandler handler)
{
if (!_windowHandlers.ContainsKey(windowName))
{
_windowHandlers[windowName] = handler;
}
else
{
_windowHandlers[windowName] += handler;
}
}
// 注销窗口
public void UnregisterWindow(string windowName, MessageReceivedHandler handler)
{
if (_windowHandlers.ContainsKey(windowName))
{
_windowHandlers[windowName] -= handler;
if (_windowHandlers[windowName] == null)
{
_windowHandlers.Remove(windowName);
}
}
}
// 发送消息到特定窗口
public void SendToWindow(string targetWindow, WindowMessage message)
{
if (_windowHandlers.ContainsKey(targetWindow))
{
_windowHandlers[targetWindow]?.Invoke(message);
}
}
// 广播消息到所有窗口
public void Broadcast(WindowMessage message)
{
GlobalMessageReceived?.Invoke(message);
foreach (var handler in _windowHandlers.Values)
{
handler?.Invoke(message);
}
}
}
// 3. 基础窗口类
public class BaseWindow : Form
{
protected string WindowName { get; set; }
public BaseWindow(string name)
{
WindowName = name;
this.Text = name;
this.FormClosed += BaseWindow_FormClosed;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// 注册到事件管理器
WindowEventManager.Instance.RegisterWindow(WindowName, HandleMessage);
WindowEventManager.Instance.GlobalMessageReceived += HandleGlobalMessage;
}
protected virtual void HandleMessage(WindowMessage message)
{
// 子类重写处理特定消息
if (message.Receiver == WindowName || message.Receiver == "ALL")
{
Console.WriteLine($"[{WindowName}] Received: {message.MessageType} from {message.Sender}");
}
}
protected virtual void HandleGlobalMessage(WindowMessage message)
{
// 处理全局广播消息
Console.WriteLine($"[{WindowName}] Global: {message.MessageType}");
}
protected void SendMessage(string targetWindow, string messageType, object data)
{
var message = new WindowMessage(WindowName, targetWindow, messageType, data);
WindowEventManager.Instance.SendToWindow(targetWindow, message);
}
protected void BroadcastMessage(string messageType, object data)
{
var message = new WindowMessage(WindowName, "ALL", messageType, data);
WindowEventManager.Instance.Broadcast(message);
}
private void BaseWindow_FormClosed(object sender, FormClosedEventArgs e)
{
// 注销事件
WindowEventManager.Instance.UnregisterWindow(WindowName, HandleMessage);
WindowEventManager.Instance.GlobalMessageReceived -= HandleGlobalMessage;
}
}
// 4. 具体窗口实现
public class MainWindow : BaseWindow
{
private Button btnOpenChild;
private Button btnSendMessage;
private TextBox txtMessage;
private ListBox lstLog;
private List<ChildWindow> childWindows;
public MainWindow() : base("MainWindow")
{
InitializeComponents();
childWindows = new List<ChildWindow>();
}
private void InitializeComponents()
{
this.Size = new System.Drawing.Size(600, 500);
// 打开子窗口按钮
btnOpenChild = new Button
{
Text = "打开子窗口",
Location = new System.Drawing.Point(10, 10),
Size = new System.Drawing.Size(100, 30)
};
btnOpenChild.Click += BtnOpenChild_Click;
// 发送消息按钮
btnSendMessage = new Button
{
Text = "发送消息",
Location = new System.Drawing.Point(120, 10),
Size = new System.Drawing.Size(100, 30)
};
btnSendMessage.Click += BtnSendMessage_Click;
// 消息文本框
txtMessage = new TextBox
{
Location = new System.Drawing.Point(230, 15),
Size = new System.Drawing.Size(200, 20)
};
// 日志列表框
lstLog = new ListBox
{
Location = new System.Drawing.Point(10, 50),
Size = new System.Drawing.Size(560, 400)
};
this.Controls.Add(btnOpenChild);
this.Controls.Add(btnSendMessage);
this.Controls.Add(txtMessage);
this.Controls.Add(lstLog);
}
private void BtnOpenChild_Click(object sender, EventArgs e)
{
var child = new ChildWindow($"ChildWindow{childWindows.Count + 1}");
child.Show();
childWindows.Add(child);
AddLog($"创建子窗口: {child.WindowName}");
}
private void BtnSendMessage_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtMessage.Text))
{
// 发送到所有子窗口
BroadcastMessage("USER_MESSAGE", txtMessage.Text);
AddLog($"广播消息: {txtMessage.Text}");
txtMessage.Clear();
}
}
protected override void HandleMessage(WindowMessage message)
{
base.HandleMessage(message);
if (message.MessageType == "CHILD_RESPONSE")
{
AddLog($"收到响应: {message.Data} from {message.Sender}");
}
else if (message.MessageType == "CHILD_CLOSED")
{
AddLog($"子窗口关闭: {message.Sender}");
}
}
private void AddLog(string message)
{
if (lstLog.InvokeRequired)
{
lstLog.Invoke(new Action(() => AddLog(message)));
}
else
{
lstLog.Items.Add($"[{DateTime.Now:HH:mm:ss}] {message}");
lstLog.SelectedIndex = lstLog.Items.Count - 1;
}
}
}
public class ChildWindow : BaseWindow
{
private Button btnSendToMain;
private Button btnBroadcast;
private TextBox txtMessage;
private ListBox lstLog;
public ChildWindow(string name) : base(name)
{
InitializeComponents();
}
private void InitializeComponents()
{
this.Size = new System.Drawing.Size(400, 300);
btnSendToMain = new Button
{
Text = "发送到主窗口",
Location = new System.Drawing.Point(10, 10),
Size = new System.Drawing.Size(120, 30)
};
btnSendToMain.Click += BtnSendToMain_Click;
btnBroadcast = new Button
{
Text = "广播到所有",
Location = new System.Drawing.Point(140, 10),
Size = new System.Drawing.Size(120, 30)
};
btnBroadcast.Click += BtnBroadcast_Click;
txtMessage = new TextBox
{
Location = new System.Drawing.Point(10, 50),
Size = new System.Drawing.Size(250, 20)
};
lstLog = new ListBox
{
Location = new System.Drawing.Point(10, 80),
Size = new System.Drawing.Size(360, 180)
};
this.Controls.Add(btnSendToMain);
this.Controls.Add(btnBroadcast);
this.Controls.Add(txtMessage);
this.Controls.Add(lstLog);
}
private void BtnSendToMain_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtMessage.Text))
{
SendMessage("MainWindow", "CHILD_RESPONSE", txtMessage.Text);
AddLog($"发送到主窗口: {txtMessage.Text}");
txtMessage.Clear();
}
}
private void BtnBroadcast_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtMessage.Text))
{
BroadcastMessage("CHILD_BROADCAST", txtMessage.Text);
AddLog($"广播消息: {txtMessage.Text}");
txtMessage.Clear();
}
}
protected override void HandleMessage(WindowMessage message)
{
base.HandleMessage(message);
if (message.MessageType == "USER_MESSAGE")
{
AddLog($"收到主窗口消息: {message.Data}");
}
}
protected override void HandleGlobalMessage(WindowMessage message)
{
base.HandleGlobalMessage(message);
if (message.MessageType == "CHILD_BROADCAST" && message.Sender != WindowName)
{
AddLog($"收到广播: {message.Data} from {message.Sender}");
}
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
BroadcastMessage("CHILD_CLOSED", WindowName);
base.OnFormClosed(e);
}
private void AddLog(string message)
{
if (lstLog.InvokeRequired)
{
lstLog.Invoke(new Action(() => AddLog(message)));
}
else
{
lstLog.Items.Add($"[{DateTime.Now:HH:mm:ss}] {message}");
lstLog.SelectedIndex = lstLog.Items.Count - 1;
}
}
}
// 5. 程序入口
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainWindow());
}
}
方案二:使用中介者模式
// MediatorCommunication.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
// 1. 中介者接口
public interface IWindowMediator
{
void Register(IWindowComponent component);
void Unregister(IWindowComponent component);
void Send(string from, string to, string message, object data);
void Broadcast(string from, string message, object data);
}
// 2. 组件接口
public interface IWindowComponent
{
string Name { get; }
void Receive(string from, string message, object data);
}
// 3. 具体中介者
public class WindowMediator : IWindowMediator
{
private Dictionary<string, IWindowComponent> _components;
public WindowMediator()
{
_components = new Dictionary<string, IWindowComponent>();
}
public void Register(IWindowComponent component)
{
if (!_components.ContainsKey(component.Name))
{
_components[component.Name] = component;
}
}
public void Unregister(IWindowComponent component)
{
_components.Remove(component.Name);
}
public void Send(string from, string to, string message, object data)
{
if (_components.ContainsKey(to))
{
_components[to].Receive(from, message, data);
}
}
public void Broadcast(string from, string message, object data)
{
foreach (var component in _components.Values.Where(c => c.Name != from))
{
component.Receive(from, message, data);
}
}
public List<string> GetRegisteredWindows()
{
return _components.Keys.ToList();
}
}
// 4. 中介者窗口基类
public abstract class MediatorWindow : Form, IWindowComponent
{
protected IWindowMediator Mediator { get; private set; }
public abstract string Name { get; }
public MediatorWindow(IWindowMediator mediator)
{
Mediator = mediator;
this.FormClosed += (s, e) => Mediator.Unregister(this);
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Mediator.Register(this);
}
public abstract void Receive(string from, string message, object data);
protected void SendTo(string targetWindow, string message, object data)
{
Mediator.Send(Name, targetWindow, message, data);
}
protected void Broadcast(string message, object data)
{
Mediator.Broadcast(Name, message, data);
}
}
// 5. 使用示例
public class MediatorMainWindow : MediatorWindow
{
public override string Name => "MainWindow";
private ListBox lstMessages;
public MediatorMainWindow(IWindowMediator mediator) : base(mediator)
{
InitializeComponents();
}
private void InitializeComponents()
{
this.Text = "主窗口 (中介者模式)";
this.Size = new System.Drawing.Size(500, 400);
lstMessages = new ListBox
{
Dock = DockStyle.Fill
};
var btnOpen = new Button
{
Text = "打开子窗口",
Dock = DockStyle.Top,
Height = 30
};
btnOpen.Click += (s, e) =>
{
var child = new MediatorChildWindow(Mediator, $"Child{new Random().Next(1000)}");
child.Show();
};
this.Controls.Add(lstMessages);
this.Controls.Add(btnOpen);
}
public override void Receive(string from, string message, object data)
{
AddLog($"来自 {from}: {message} - {data}");
}
private void AddLog(string text)
{
if (lstMessages.InvokeRequired)
{
lstMessages.Invoke(new Action(() => AddLog(text)));
}
else
{
lstMessages.Items.Add($"[{DateTime.Now:HH:mm:ss}] {text}");
}
}
}
public class MediatorChildWindow : MediatorWindow
{
private TextBox txtMessage;
private string _name;
public override string Name => _name;
public MediatorChildWindow(IWindowMediator mediator, string name) : base(mediator)
{
_name = name;
InitializeComponents();
}
private void InitializeComponents()
{
this.Text = _name;
this.Size = new System.Drawing.Size(300, 200);
txtMessage = new TextBox
{
Location = new System.Drawing.Point(10, 10),
Size = new System.Drawing.Size(200, 20)
};
var btnSend = new Button
{
Text = "发送到主窗口",
Location = new System.Drawing.Point(10, 40),
Size = new System.Drawing.Size(120, 30)
};
btnSend.Click += (s, e) =>
{
if (!string.IsNullOrEmpty(txtMessage.Text))
{
SendTo("MainWindow", "CHILD_MESSAGE", txtMessage.Text);
txtMessage.Clear();
}
};
var btnBroadcast = new Button
{
Text = "广播",
Location = new System.Drawing.Point(140, 40),
Size = new System.Drawing.Size(120, 30)
};
btnBroadcast.Click += (s, e) =>
{
if (!string.IsNullOrEmpty(txtMessage.Text))
{
Broadcast("BROADCAST_MESSAGE", txtMessage.Text);
txtMessage.Clear();
}
};
this.Controls.Add(txtMessage);
this.Controls.Add(btnSend);
this.Controls.Add(btnBroadcast);
}
public override void Receive(string from, string message, object data)
{
// 处理接收到的消息
}
}
方案三:使用消息队列(高级方案)
// MessageQueueCommunication.cs
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
// 1. 消息队列管理器
public class WindowMessageQueue
{
private static WindowMessageQueue _instance;
private static readonly object _lock = new object();
// 消息队列
private ConcurrentDictionary<string, BlockingCollection<WindowMessage>> _queues;
private ConcurrentDictionary<string, List<Action<WindowMessage>>> _subscribers;
// 后台处理线程
private CancellationTokenSource _cancellationTokenSource;
private List<Task> _workerTasks;
private WindowMessageQueue()
{
_queues = new ConcurrentDictionary<string, BlockingCollection<WindowMessage>>();
_subscribers = new ConcurrentDictionary<string, List<Action<WindowMessage>>>();
_cancellationTokenSource = new CancellationTokenSource();
_workerTasks = new List<Task>();
}
public static WindowMessageQueue Instance
{
get
{
lock (_lock)
{
return _instance ?? (_instance = new WindowMessageQueue());
}
}
}
// 创建窗口队列
public void CreateQueue(string windowName)
{
_queues.TryAdd(windowName, new BlockingCollection<WindowMessage>());
_subscribers.TryAdd(windowName, new List<Action<WindowMessage>>());
// 启动消息处理任务
var task = Task.Run(() => ProcessMessages(windowName), _cancellationTokenSource.Token);
_workerTasks.Add(task);
}
// 订阅消息
public void Subscribe(string windowName, Action<WindowMessage> handler)
{
if (_subscribers.ContainsKey(windowName))
{
_subscribers[windowName].Add(handler);
}
}
// 发送消息
public void SendMessage(string targetWindow, WindowMessage message)
{
if (_queues.ContainsKey(targetWindow))
{
_queues[targetWindow].Add(message);
}
}
// 广播消息
public void Broadcast(WindowMessage message, params string[] excludeWindows)
{
var excludeSet = new HashSet<string>(excludeWindows);
foreach (var kvp in _queues)
{
if (!excludeSet.Contains(kvp.Key))
{
kvp.Value.Add(message);
}
}
}
// 处理消息
private void ProcessMessages(string windowName)
{
var queue = _queues[windowName];
var token = _cancellationTokenSource.Token;
try
{
foreach (var message in queue.GetConsumingEnumerable(token))
{
if (_subscribers.ContainsKey(windowName))
{
foreach (var handler in _subscribers[windowName])
{
// 在UI线程上执行
Application.CurrentForm?.Invoke(new Action(() =>
{
handler(message);
}));
}
}
}
}
catch (OperationCanceledException)
{
// 正常取消
}
}
// 清理资源
public void Shutdown()
{
_cancellationTokenSource.Cancel();
Task.WhenAll(_workerTasks).Wait();
foreach (var queue in _queues.Values)
{
queue.CompleteAdding();
queue.Dispose();
}
_queues.Clear();
_subscribers.Clear();
}
}
// 扩展类,用于获取当前窗体
public static class ApplicationHelper
{
public static Form CurrentForm { get; set; }
}
// 2. 消息队列窗口基类
public class QueueWindow : Form
{
protected string WindowName { get; }
public QueueWindow(string name)
{
WindowName = name;
this.Text = name;
// 注册当前窗体
ApplicationHelper.CurrentForm = this;
// 创建消息队列
WindowMessageQueue.Instance.CreateQueue(WindowName);
this.FormClosed += (s, e) =>
{
// 清理工作
if (ApplicationHelper.CurrentForm == this)
{
ApplicationHelper.CurrentForm = null;
}
};
}
protected void SubscribeToMessages(Action<WindowMessage> handler)
{
WindowMessageQueue.Instance.Subscribe(WindowName, handler);
}
protected void SendToQueue(string targetWindow, WindowMessage message)
{
WindowMessageQueue.Instance.SendMessage(targetWindow, message);
}
protected void BroadcastToQueue(WindowMessage message, params string[] excludeWindows)
{
WindowMessageQueue.Instance.Broadcast(message, excludeWindows);
}
}
方案四:使用WPF的MVVM模式 + 消息总线
// WPF MVVM + Message Bus
// MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
// 订阅消息
MessageBus.Default.Subscribe<string>(this, "StatusUpdate", OnStatusUpdate);
MessageBus.Default.Subscribe<DataMessage>(this, "DataChanged", OnDataChanged);
}
private void OnStatusUpdate(string status)
{
// 更新UI
Dispatcher.Invoke(() =>
{
txtStatus.Text = status;
});
}
private void OnDataChanged(DataMessage data)
{
// 处理数据变化
Dispatcher.Invoke(() =>
{
// 更新数据绑定
});
}
private void OpenChildWindow_Click(object sender, RoutedEventArgs e)
{
var childWindow = new ChildWindow();
childWindow.Owner = this;
childWindow.Show();
}
protected override void OnClosed(EventArgs e)
{
// 取消订阅
MessageBus.Default.Unsubscribe(this);
base.OnClosed(e);
}
}
// MainViewModel.cs
public class MainViewModel : INotifyPropertyChanged
{
private ObservableCollection<string> _messages;
public ObservableCollection<string> Messages
{
get => _messages;
set
{
_messages = value;
OnPropertyChanged();
}
}
public ICommand SendMessageCommand { get; }
public MainViewModel()
{
Messages = new ObservableCollection<string>();
SendMessageCommand = new RelayCommand(SendMessage);
// 订阅全局消息
MessageBus.Default.Subscribe<WindowMessage>(this, "AnyMessage", OnMessageReceived);
}
private void SendMessage()
{
// 发送消息到所有窗口
MessageBus.Default.Publish("GlobalMessage", "Hello from Main Window!");
}
private void OnMessageReceived(WindowMessage message)
{
Messages.Add($"[{message.Sender}] {message.Content}");
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
// MessageBus.cs (简单的消息总线实现)
public class MessageBus
{
private static MessageBus _instance;
public static MessageBus Default => _instance ??= new MessageBus();
private readonly Dictionary<string, List<WeakReference>> _subscribers;
private readonly object _lock = new object();
private MessageBus()
{
_subscribers = new Dictionary<string, List<WeakReference>>();
}
public void Subscribe<T>(object subscriber, string message, Action<T> handler)
{
lock (_lock)
{
if (!_subscribers.ContainsKey(message))
{
_subscribers[message] = new List<WeakReference>();
}
var handlerWrapper = new HandlerWrapper<T>(handler);
_subscribers[message].Add(new WeakReference(subscriber));
}
}
public void Publish<T>(string message, T data)
{
lock (_lock)
{
if (_subscribers.ContainsKey(message))
{
foreach (var reference in _subscribers[message].ToList())
{
if (reference.IsAlive && reference.Target is Action<T> handler)
{
try
{
handler(data);
}
catch (Exception ex)
{
// 处理异常
}
}
}
}
}
}
public void Unsubscribe(object subscriber)
{
lock (_lock)
{
foreach (var message in _subscribers.Keys.ToList())
{
_subscribers[message].RemoveAll(r => !r.IsAlive || r.Target == subscriber);
}
}
}
private class HandlerWrapper<T>
{
private readonly Action<T> _handler;
public HandlerWrapper(Action<T> handler)
{
_handler = handler;
}
public static implicit operator Action<T>(HandlerWrapper<T> wrapper)
{
return wrapper._handler;
}
}
}
方案五:使用.NET Core的依赖注入和事件总线
// Startup.cs (ASP.NET Core风格)
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// 注册窗口服务
services.AddSingleton<IWindowManager, WindowManager>();
services.AddSingleton<IEventAggregator, EventAggregator>();
// 注册窗口
services.AddTransient<MainWindow>();
services.AddTransient<ChildWindow>();
services.AddTransient<SettingsWindow>();
// 注册事件处理器
services.AddTransient<IEventHandler<UserLoggedInEvent>, UserEventHandler>();
services.AddTransient<IEventHandler<DataUpdatedEvent>, DataEventHandler>();
}
}
// WindowManager.cs
public interface IWindowManager
{
void ShowWindow<T>() where T : Form;
void SendMessage(string windowName, object message);
void RegisterWindow(string name, Form window);
void UnregisterWindow(string name);
}
public class WindowManager : IWindowManager
{
private readonly Dictionary<string, Form> _windows;
private readonly IEventAggregator _eventAggregator;
public WindowManager(IEventAggregator eventAggregator)
{
_windows = new Dictionary<string, Form>();
_eventAggregator = eventAggregator;
}
public void ShowWindow<T>() where T : Form
{
var form = ActivatorUtilities.CreateInstance<T>(ServiceProvider);
form.Show();
RegisterWindow(form.Name, form);
}
public void SendMessage(string windowName, object message)
{
if (_windows.ContainsKey(windowName))
{
var window = _windows[windowName];
if (window is IMessageReceiver receiver)
{
receiver.ReceiveMessage(message);
}
}
}
public void RegisterWindow(string name, Form window)
{
_windows[name] = window;
window.FormClosed += (s, e) => UnregisterWindow(name);
}
public void UnregisterWindow(string name)
{
_windows.Remove(name);
}
// 通过事件聚合器发布事件
public void PublishEvent<TEvent>(TEvent @event) where TEvent : IEvent
{
_eventAggregator.Publish(@event);
}
}
// EventAggregator.cs
public interface IEventAggregator
{
void Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent;
void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent;
void Publish<TEvent>(TEvent @event) where TEvent : IEvent;
}
public class EventAggregator : IEventAggregator
{
private readonly Dictionary<Type, List<object>> _handlers;
public EventAggregator()
{
_handlers = new Dictionary<Type, List<object>>();
}
public void Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
{
var eventType = typeof(TEvent);
if (!_handlers.ContainsKey(eventType))
{
_handlers[eventType] = new List<object>();
}
_handlers[eventType].Add(handler);
}
public void Publish<TEvent>(TEvent @event) where TEvent : IEvent
{
var eventType = typeof(TEvent);
if (_handlers.ContainsKey(eventType))
{
foreach (var handler in _handlers[eventType])
{
((IEventHandler<TEvent>)handler).Handle(@event);
}
}
}
public void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
{
var eventType = typeof(TEvent);
if (_handlers.ContainsKey(eventType))
{
_handlers[eventType].Remove(handler);
}
}
}
使用示例和测试
// Program.cs - 测试代码
class Program
{
[STAThread]
static void Main()
{
// 测试方案一:事件通信
TestEventCommunication();
// 测试方案二:中介者模式
TestMediatorPattern();
// 测试方案三:消息队列
TestMessageQueue();
}
static void TestEventCommunication()
{
Console.WriteLine("=== 测试事件通信模式 ===");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var mainWindow = new MainWindow();
// 启动应用
Application.Run(mainWindow);
}
static void TestMediatorPattern()
{
Console.WriteLine("=== 测试中介者模式 ===");
var mediator = new WindowMediator();
var mainWindow = new MediatorMainWindow(mediator);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(mainWindow);
}
static void TestMessageQueue()
{
Console.WriteLine("=== 测试消息队列 ===");
// 创建并启动窗口
var window1 = new QueueWindow("Window1");
var window2 = new QueueWindow("Window2");
window1.SubscribeToMessages(msg =>
{
Console.WriteLine($"Window1收到: {msg.MessageType} from {msg.Sender}");
});
window2.SubscribeToMessages(msg =>
{
Console.WriteLine($"Window2收到: {msg.MessageType} from {msg.Sender}");
});
// 发送测试消息
var testMessage = new WindowMessage("System", "Window1", "TEST", "Hello");
WindowMessageQueue.Instance.SendMessage("Window1", testMessage);
// 注意:实际使用时需要创建Form并运行Application
}
}
参考代码 C#实现的多窗口互相通信 www.3dddown.com/cnb/122448.html
比较总结
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 事件/委托 | 简单直观,.NET原生支持 | 强耦合,需要管理事件订阅 | 小型应用,窗口数量少 |
| 中介者模式 | 解耦,集中管理 | 中介者可能成为瓶颈 | 中型应用,需要集中控制 |
| 消息队列 | 异步处理,高并发 | 实现复杂,需要管理线程 | 大型应用,高并发需求 |
| 消息总线 | 松耦合,易于扩展 | 需要额外框架支持 | MVVM应用,WPF项目 |
| 依赖注入 | 可测试,松耦合 | 配置复杂,学习成本高 | 企业级应用,需要高可测试性 |
最佳实践建议
- 小型项目:使用事件/委托方案一,简单高效
- 中型项目:使用中介者模式或消息总线,平衡复杂度与功能
- 大型项目:使用消息队列或依赖注入,确保可扩展性和可维护性
- WPF项目:优先使用MVVM + 消息总线方案
- 跨线程通信:务必使用Control.Invoke或Dispatcher.Invoke更新UI

浙公网安备 33010602011771号