有没有一种明确的方法来识别哪些事件订阅会导致内存泄漏,哪些不会;t

本文关键字:内存 泄漏 事件 一种 方法 有没有 识别 | 更新日期: 2023-09-27 18:09:06

我很清楚事件订阅和取消订阅的语法。

myEvent += myEventHandler;  // subscribe
myEvent -= myEventHandler;  // unsubscribe

我喜欢事件订阅的lambda语法(自身包含在块中(,但如果需要取消订阅(以避免内存泄漏(,我不能使用此语法。

因此,我的问题是,什么样的事件需要取消订阅,哪些事件可以忽略,由GC处理?例如,我在UWP应用程序中使用了以下内容,它们需要取消订阅吗?如果需要,为什么?

  • 视图页的PointerMoved事件(Windows.UI.Xaml ns((代码隐藏(
  • 来自与订阅页面位于同一命名空间中的另一个页面的事件。当订阅页面在用户控制下导航时,包含事件的源页面将作为菜单容器保留

有没有一种明确的方法来识别哪些事件订阅会导致内存泄漏,哪些不会;t

C#事件是该语言中考虑最少的特性之一。我的建议是:永远不要使用它们。如果意外添加了一个已经添加的事件处理程序,那么默认实现实际上会添加两次该处理程序。这是一个很难检测和排除故障的错误。此外,如果您意外地删除了从未添加的事件处理程序,则不会出现错误:它以静默方式失败。本质上,它是在折磨你:它告诉你"是的,完成了!",欺骗你相信你的三段论是正确的,而事实上它是错误的。这不是开发软件的方法。我知道全世界有很多人都在开发这样的软件,他们以某种方式凑合着用,我只能说我为他们感到难过。不要那样对自己。

实现您自己的观察者/可观察模式,断言不添加任何内容两次,不添加第一次就不删除任何内容。在可观察对象的生命周期结束时,断言所有观察者列表都是空的,这意味着所有观察者都懒得注销。是的,垃圾处理是一颗神奇的子弹,可以让我们不用担心这样的事情,但你猜怎么着,事实并非如此。当检查纸上琐碎的例子和学术练习时,一切看起来都很好,但一旦事情开始变得有点复杂,让魔法来处理就不再管用了。

一旦你发现某个观察者从未从可观察对象中注销,你就需要找出该观察者的分配位置和/或注册位置。您可以通过获取当前堆栈跟踪并将其存储在观察器中来实现这一点,这样,如果后来发现观察器处于活动状态,您就可以转储其堆栈跟踪。获取堆栈跟踪的方法如下:StackTrace stackTrace = new StackTrace();注意,这非常慢,(微软只知道为什么,(所以只有在实际需要时才使用它,也就是说,在对您知道有错误的特定类进行故障排除时。修复错误后立即将其删除。