首页 > 系统相关 >【译】解开托管内存的秘密:深入了解事件处理程序泄漏!

【译】解开托管内存的秘密:深入了解事件处理程序泄漏!

时间:2024-01-26 09:04:49浏览次数:26  
标签:泄漏 订阅 应用程序 处理程序 内存 我们 事件

  事件处理程序泄漏已经存在很长时间了,这是 WPF (Windows Presentation Foundation)开发人员经常要处理的最麻烦的问题之一。您可能会想:是什么让事件处理程序泄漏如此重要?事件处理程序泄漏很容易引起,只需忘记取消订阅事件即可。此外,它们很难发现,甚至更难修复。

  在更新17.9预览1中引入的 Visual Studio 托管内存使用工具中添加的新见解大大简化了发现/修复这些泄漏的过程。它提供有关哪些对象正在泄漏及其订阅的事件的信息。

什么是事件处理程序泄漏?

  当对象在功能上无法使用时,没有被识别为垃圾收集时,它会在堆上泄漏。这意味着它将无意中在内存中保持活动状态。事件处理程序因导致这种情况而臭名昭著。这是因为事件处理程序在对象和它订阅的事件之间创建了一个直接引用。

  在本例中,我们有一个 Publisher 和 Subscriber 类。当 Subscriber 调用 Subscribe 时,MyEvent 将在堆中链接 Publisher 和 Subscriber:

  这样做的问题是,如果 Subscriber 忘记取消订阅,这些引用将保留在堆上,从而泄漏 Subscriber。这里最简单的解决方案是简单地调用 Unsubscribe 方法,但是在更复杂的应用程序中,很难跟踪对象的订阅以及何时退订。这就是 Memory Analyzer 可以帮助开发人员解决这些问题的地方。

好吧,让我们看看如何解决它?

  为了证明这一点,我们将对一个示例 WPF 应用程序进行演练调试,以查找事件处理程序泄漏:

  在本例中,我们有一个窗口,它在打开时订阅 dispatcherTimer_Tick 事件。事件在做什么并不重要。这段代码的重要部分是,当窗口关闭时,我们忘记取消订阅事件:

  这里取消订阅语句的注释是有问题的,因为它在窗口关闭时不再正确地取消订阅,并且会导致泄漏。为了找到它,让我们开始调试这个应用程序(F5)。为简单起见,让我们假设 main() 正确地导致泄漏,它打开 AdWindow,导致它订阅一个事件,然后关闭它。

  首先,我们需要打开诊断工具窗口。要在调试会话中访问它,请执行 Debug ->  Windows ->  Diagnostic Tools。

  当它在调试会话中打开时,它应该是这样的:

  此窗口显示正在调试的应用程序的堆的总体大小和 CPU 百分比。当我们单击相机图标拍摄快照时,我们可以通过单击 Objects 下的值来查看堆并访问事件处理程序泄漏见解。

  进入快照的堆视图后,导航到 Insights(见解):

  我们终于到站了!在 Insights 选项卡中,我们可以看到泄漏事件处理程序的列表,并且我们可以看到泄漏窗口的显示。此外,我们可以看到该泄漏所浪费的总量。仅仅是这个简单的例子就造成了 4.93 KB 的泄漏!这是因为窗口有一个完整的子树,它引用的对象也会因为忘记取消订阅而泄漏。

  此外,您可以通过点击“Show Just My code”来过滤掉所有的系统代码,只显示 AdWindow。

  这很酷,但现在怎么办?

  到目前为止,我们已经成功地确定了我们的应用程序中的泄漏。现在,如果我们想要修复它,我们可以点击“View Details”来查看有关问题的更多信息,更重要的是,如何修复它。

  这个视图向我们展示了一些关于泄漏的关键信息。我们可以看到对象的地址,它持有的事件处理程序,最重要的是,它订阅的对象。这传达了要解决这个问题,AdWindow 必须从 DispatcherTimer 取消订阅。此外,您还可以看到 AdWindow 对象的引用图。“Referenced Objects”选项卡显示了由于 AdWindow 而泄漏的额外对象的数量。

我们还能做什么?

  如果您已经读到这里了,你可能会对这种见解的其他用途感兴趣。例如,检测逻辑可以处理任何类型的事件处理程序。考虑前面的带有发布者和订阅者类的控制台应用程序,如果我们创建自己的事件处理程序,我们仍然可以检测到它。

告诉我们您的想法!

  在未来的版本中,这种体验还会有很多改进。请下载最新的 Visual Studio 预览版并提供您的反馈。请在 Visual Studio 中通过“Report a Problem”或直接在开发者社区站点提出问题并提供反馈。

 

原文链接:https://devblogs.microsoft.com/visualstudio/unlocking-the-secrets-of-managed-memory-dive-into-event-handler-leak-insights/

 

标签:泄漏,订阅,应用程序,处理程序,内存,我们,事件
From: https://www.cnblogs.com/MeteorSeed/p/17987012

相关文章

  • OpenMP学习 第十一章 同步与OpenMP内存模型
    第十一章同步与OpenMP内存模型内存一致性模型OpenMP线程在共享内存中执行,共享内存是组中所有线程都可以访问的地址空间,其中存储着变量.使共享内存系统高效运行的唯一方法是允许线程保持一个临时的内存视图,该视图驻留在处理器和内存RAM之间的内存结构中.当线程通过共享内存......
  • .NET GC的SustainedLowLatency模式引发内存的问题
    最近遇到一个问题,应用的内存占用升上去后一直降不下来,打了dump文件后发现GC的Generation0上有很多空白区间没释放,按道理第0代堆是经常回收的,怎么会有那么多空白区间呢?查阅了相关文档后,发现这是由代码中的System.Runtime.GCSettings.LatencyMode=System.Runtime.GCLatencyMode......
  • OB的内存&转储&合并
    OB的内存&转储&合并 转:https://www.cnblogs.com/z-uncle/p/17916448.html内存OBserver内存:物理总内存=OBserver内存+OS剩余内存。OBserver的内存分为两部分,一部分是system内存,一部分是租户内存。通过参数设定observer占用的内存上限:memory_limit_percentage=80--->80%......
  • [转帖]内存(DDR/DDR2/DDR3/DDR4)的速度等级和时钟频率
    以下全部图片均来自镁光(Micron)公司产品的数据手册。DDR:以MT48LCxx型号的DDR内存芯片为例,数据手册中给出如图1所示的一个表格。从表格中可以看出它的主频(ClockFrequency)。图1不同速度等级的DDR主频它的主频与传输数据的频率相同。我们可以从时序图中观察出来。随便......
  • Java内存分配与回收策略
    HotSpot虚拟机GC分类针对HotSpot虚拟机的实现,GC可以分为2大类:部分收集(PartialGC)新生代收集(MinorGC/YoungGC):回收新生代,因为新生代对象存活时间很短,因此MinorGC会频繁执行,执行的速度一般也会比较快。老年代收集(MajorGC/OldGC):只对老年代进行垃圾收集。需......
  • 最佳实践:如何发现、修复和防止 Node.js 内存泄漏
    这篇文章将介绍什么是内存泄漏以及如何在Node.js应用程序中避免内存泄漏。什么是内存泄漏?在深入研究内存泄漏的细节之前,有必要先了解什么是内存生命周期。为已定义变量分配内存对分配的内存进行读、写等操作。使用后,释放分配的内存内存泄漏是指当程序没有释放它分配的内存时,即生......
  • 内存带宽读写工具 Stream
    一.工具介绍前言stream测试得到的是可持续运行的内存带宽最大值,而并不是一般的硬件厂商提供的理论最大值,具有如下特点:1.主要有四种数组运算,测试的内存带宽的性能分别是:数组的复制(Copy)、数组的尺度变换(Scale)、数组的矢量求和(Add)、数组的复合矢量求和(Triad)2.数组的值......
  • [转帖]深入JVM - Code Cache内存池
    深入JVM-CodeCache内存池1.本文内容本文简要介绍JVM的CodeCache(本地代码缓存池)。2.CodeCache简要介绍简单来说,JVM会将字节码编译为本地机器码,并使用CodeCache来保存。每一个可执行的本地代码块,称为一个nmethod。nmethod可能对应一个完整的Java方法,或......
  • [转帖]一文深度讲解JVM 内存分析工具 MAT及实践(建议收藏)
    https://juejin.cn/post/69116243284721336461.前言熟练掌握MAT是Java高手的必备能力,但实践时大家往往需面对众多功能,眼花缭乱不知如何下手,小编也没有找到一篇完善的教学素材,所以整理本文帮大家系统掌握MAT分析工具。本文详细讲解MAT众多内存分析工具功能......
  • 【译】为什么在内存成为核心组件之前我们无法实现 AGI
    原作:史蒂夫·纽曼引子:思考的难点在于知道要思考什么 上次,我描述了像ChatGPT这样的大型语言模型所面临的严峻挑战:它们是在完成的文本上进行训练的,而对创建复杂的文章所必需的概述、充实、修改和迭代过程没有任何见解、设计、代码、战略计划或其他复杂工件。为了实现人类水平......