在 C# 开发中,事件(Event)是一种非常常见的编程机制,用于实现对象之间的松耦合通信。然而,如果不小心处理,事件订阅很容易导致内存泄漏问题。这是因为事件发布者(Publisher)持有了对事件订阅者(Subscriber)的强引用,即使订阅者已经不再使用,也无法被垃圾回收器回收。
为了解决这个问题,C# 弱事件(Weak Event)模式应运而生。本文将手把手教你如何在 C# 中正确使用弱事件,避免内存泄漏,并确保事件能够安全地订阅和取消订阅。
弱事件(Weak Event)是一种设计模式,它允许事件订阅者在不被事件发布者强引用的情况下接收事件通知。这样,当订阅者对象不再被其他代码引用时,即使它仍然“订阅”了某个事件,也可以被垃圾回收器正常回收,从而避免内存泄漏。
考虑以下常见场景:
这就是典型的C#事件内存泄漏问题。使用弱事件可以有效解决这一问题。
C# 本身没有内置的弱事件机制,但我们可以借助 WeakReference<T> 类手动实现,或者使用 .NET 提供的 WeakEventManager(主要用于 WPF)。下面我们将展示一个通用的手动实现方式。
// 定义一个泛型弱事件管理器public class WeakEventManager<TEventArgs> where TEventArgs : EventArgs{ private readonly List<WeakReference<Action<object, TEventArgs>>> _handlers = new(); public void Subscribe(Action<object, TEventArgs> handler) { if (handler == null) throw new ArgumentNullException(nameof(handler)); _handlers.Add(new WeakReference<Action<object, TEventArgs>>(handler)); } public void Unsubscribe(Action<object, TEventArgs> handler) { if (handler == null) return; _handlers.RemoveAll(wr => { if (wr.TryGetTarget(out var target)) return target == handler; return true; // 清理已失效的引用 }); } public void Raise(object sender, TEventArgs e) { // 清理无效引用并调用有效处理器 var validHandlers = new List<Action<object, TEventArgs>>(); _handlers.RemoveAll(wr => { if (wr.TryGetTarget(out var target)) { validHandlers.Add(target); return false; } return true; // 移除无效引用 }); foreach (var handler in validHandlers) { handler(sender, e); } }} // 发布者类public class Publisher{ private readonly WeakEventManager<EventArgs> _eventManager = new(); public event Action<object, EventArgs> MyEvent { add => _eventManager.Subscribe(value); remove => _eventManager.Unsubscribe(value); } public void DoSomething() { Console.WriteLine("触发事件..."); _eventManager.Raise(this, EventArgs.Empty); }}// 订阅者类class Subscriber{ public void OnMyEvent(object sender, EventArgs e) { Console.WriteLine("收到事件!"); }}// 使用示例class Program{ static void Main() { var publisher = new Publisher(); { var subscriber = new Subscriber(); publisher.MyEvent += subscriber.OnMyEvent; publisher.DoSomething(); // 输出:触发事件... 收到事件! } // subscriber 超出作用域 // 强制垃圾回收 GC.Collect(); GC.WaitForPendingFinalizers(); publisher.DoSomething(); // 只输出:触发事件...(不会再次触发事件) }} WeakEventManager,但在非 WPF 项目中建议使用自定义实现;Unsubscribe,以提升性能(尽管不是必须)。掌握C#事件订阅中的弱事件模式,是编写高性能、无内存泄漏应用程序的关键技能之一。通过本文的详细讲解和代码示例,即使是初学者也能理解并应用弱事件来提升代码质量。
希望这篇教程能帮助你彻底搞懂弱事件模式!如果你觉得有用,欢迎分享给更多开发者。
本文由主机测评网于2025-12-09发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025125377.html