C#常见内存泄漏

背景

在开发中由于对语言特性不了解或经验不足或疏忽,往往会造成一些低级bug。而内存泄漏就是最常见的一个,这个问题在测试过程中,因为操作频次低,而不能完全被暴露出来;而在正式使用时,由于使用次数增加,这个问题在很快就会出现。一旦出现就会导致程序直接退出或报错……使用中得益于使用量的增加,未被回收的小对象不断实例化,数量的叠加,导致内存使用率会随时间的增长而增加,直到影响程序的正常执行。

为了警醒鄙人,同时方便以后查阅,将在项目中实际处理的内存泄漏情况与处理办法进行下述总结。

常见泄漏

在C#中常见的内存泄漏主要是由于事件订阅造成:

  1. 实例类订阅静态类事件,不使用当前实例时未取消订阅,导致静态类中一直持有订阅方实例类,实例类不能释放,而每次使用时不断实例化后实例数量不断增加。
  2. 实例类中有类似timer之类定时运行的对象未释放(未dispose),导致实例类不能回收,而实例类仍不断实例化。
  3. 实例类中订阅了另一个实例类中的事件,但另一个实例类的生命周期很长(如果生命周期短,订阅方在使用完后,若被订阅方之后也完成了使命,理论上是可以很快被GC回收的),同时订阅方在未使用时也未及时取消订阅,导致被订阅方长时间持有订阅实例。
  4. 其它订阅未取消的情况。

实例类订阅静态类事件,但未取消订阅

若在构造函数中订阅静态类FolderSelect中的AllFolderg事件:

FolderSelect folderSelect = FolderSelect.Instance;
folderSelect.AllFolder += FolderSelect_AllFolder;

如果在不使用时,不执行 folderSelect.ScanAllFolder -= FolderSelect_ScanAllFolder;就会导致FolderSelect静态类一直持有订阅类,导致订阅类不能被回收。

同时由于实例类,在实例化时会运行构造函数,生成新的实例时会再次将新实例又再次订阅这个事件。那么当FolderSelect触发AllFolder事件时,新、旧实例都会执行FolderSelect_AllFolderg事件,这也可能导致一些不必要的问题。

实例类中timer未释放

在某些情况下,在对象类中会使用timer,而timer在不使用时,一定要dispose掉。由于timer在执行定时事件时会一直持有当前的对象,从而导致对象不能被回收。另.net中涉及到的timer有6种,详细见Timer Class (System.Threading) | Microsoft Learn中的详细介绍。

实例类订阅长生命周期实例类

以WINUI中常用的异常捕捉为例,若在Page的构造函数中添加了下述代码:

 AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;

即每次实例化这个Page时都会订阅CurrentDomain_FirstChanceException这个方法,而AppDomain的生命周期与程序一致,导致它会一直持有当前订阅方的实例,从而订阅方不能被回收。

其他订阅未取消

WINUI ComboBoxItem事件未取消

WINUI中的对ComboBox中的ComboBoxItem单独添加了Tapped事件,而这个Tapped事件若在不使用时未取消订阅,也会引起当前使用的对象不能被回收。

在WINUI中的ComboBox的UI代码如下:

<ComboBoxx:Name="ComboOrder"Width="268"Height="70"Margin="5,0,5,0"VerticalAlignment="Center"BorderThickness="0"FontSize="38"Foreground="White"Loaded="ComboOrder_Loaded"SelectedIndex="0"Style="{StaticResource DefaultComboBoxStyle2}"Tag="180"ToolTipService.ToolTip="排序"><ComboBoxItemx:Name="CbiPatientName"Content="患者名"Style="{StaticResource ComboBoxItemRevealStyle2}"Tag="0"Tapped="CbiName_Tapped" /><ComboBoxItemx:Name="CbiImportTime"Content="时间"Style="{StaticResource ComboBoxItemRevealStyle2}"Tag="0"Tapped="CbiImportTime_Tapped" /><ComboBoxItemx:Name="CbiPlanPhase"Content="阶段"Style="{StaticResource ComboBoxItemRevealStyle2}"Tag="0"Tapped="CbiPlanPhase_Tapped" /></ComboBox>

在上述代码中,为ComboBoxItem添加了Tapped事件,正是这个事件导致程序在退出ComboBox所在页时,它所在的Page不能及时被回收,导致再次进入时会新增它所在的Page实例。为了避免此问题,不得以重写离开页面方法 protected override void OnNavigatingFrom(NavigatingCancelEventArgs e),在这个方法中将ComboBoxItem的绑定事件全部取消。

可能原因:ComboBoxItem为ComboBox的子控件,导致ComboBoxItem的tapped事件的引用可能形成了闭包,导致它所在的Page不能被回收。后续搞清楚原因再做相应更新。

取消订阅

取消订阅——对于事件订阅造成的内存泄漏,当然是在不使用当前对象时,就及时将它订阅的事件取消订阅即可。详细可参考如何订阅和取消订阅事件 - C# 编程指南 - C# | Microsoft Learn最下方的取消订阅栏。

弱事件管理——另外事件也可以使用弱引用进行相应的操作,详细见MSDNWeakEventManager 类 (System.Windows) | Microsoft Learn。

利用诊断预防内存泄漏

除了在编程时就养成使用完订阅事件就马上取消,另外在进行测试时也可以通过VisualStudio提供的诊断工具进行诊断。使用方法如下,详细参见MSDN。

诊断工具下方,选择内存使用率,然后在内存使用率的面板左上角点击截取快照,截取完成后如下,再点击对象(差异)即可查看对象数量的情况。

在点击上图中的红圈后,如下图,在下图中左上角类型面板中搜索查看的对象。另还可在下图右上角与基线进行比较中选择一个你要比较的前一个内存快照。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/249011.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI学习(4): PyTorch实战-手写数字识别

1.介绍 在之前的文章中介绍了PyTorch的环境安装&#xff0c;和张量(tensor)的基本使用&#xff0c;为防止陷入枯燥的理论学习中&#xff0c;在这篇文章&#xff0c;我们将进行项目实战学习&#xff0c;项目主要内容: 基于MNIST数据集&#xff0c;实现一个手写数字识别的神经网…

jdk17新特性—— 密封类(Sealed Classes)

目录 一、密封类(Sealed Classes)的概述1.1、概述1.2、特性1.3、注意事项 二、密封类(Sealed Classes)代码示例2.1、密封类(Sealed Classes)代码结构示例2.2、密封类(Sealed Classes)代码示例 三、密封类(Sealed Classes)接口代码示例3.1、密封类(Sealed Classes)接口代码结构示…

浙大团队撰写75页科学语言大模型综述,全面梳理Sci-LLMs最新研究进展

大型语言模型&#xff08;LLMs&#xff09;已成为推动自然语言理解能力变革的关键力量&#xff0c;标志着人工智能通用性方面的重大突破。LLMs 的应用已超越传统自然语言的范畴&#xff0c;覆盖了各类科学学科中开发的专用科学语言系统&#xff0c;从而推动了科学语言大模型&am…

嵌入式学习第十四天

1.结构体&#xff08;2&#xff09;: &#xff08;1&#xff09;结构体类型定义 &#xff08;2&#xff09;结构体变量的定义 &#xff08;3&#xff09;结构体元素的访问 &#xff08;4&#xff09;结构体的存储: 内存对齐: char 按照1字节对齐 …

Coppeliasim倒立摆demo

首先需要将使用Python远程控制的文件导入到文件夹&#xff0c;核心是深蓝色的三个文件。 本版本为4.70&#xff0c;其文件所在位置如下图所示&#xff0c;需要注意的是&#xff0c;目前不支持Ubuntu22的远程api&#xff1a; 双击Sphere这一行的灰色文件&#xff0c;可以看到远程…

【Redis】理论基础 - 概览

文章目录 1. 定义2. 主要特性1&#xff09;内存存储2&#xff09;数据结构多样性3&#xff09;持久化4&#xff09;主从复制5&#xff09;事务支持 3. 使用场景1&#xff09;缓存2&#xff09;消息队列3&#xff09;实时统计与计数4&#xff09;分布式锁 总结 Redis&#xff08…

探索设计模式的魅力:精准解读桥接模式-用桥接模式构建可扩展的软件系统

设计模式专栏&#xff1a;http://t.csdnimg.cn/nolNS 目录 一、了解桥接模式&#xff1a;探索抽象和实现的分离 1.1 开-闭原则 1.2 组合/聚合复用原则 1.3 定义 1.4 用意 1.5 基本思想 1.6 组成部分 1.7 桥梁模式的示意性系统的结构图 二、桥接模式的优势&#xff1a…

android远程投屏应用

客户端app地址&#xff1a;https://gitee.com/youzilzk/blue1.git 服务端地址&#xff1a;https://gitee.com/youzilzk/blue-server1.git 一。服务端部署 1.安装postgres 2.导入项目下blue.sql文件 3.修改配置application.properties和config.properties&#xff0c;其中applic…

Qt 基础之QDataTime

Qt 基础之QDataTime 引言一、获取(设定)日期和时间二、时间戳三、时间计算 (重载运算符) 引言 QDataTime是Qt框架中用于处理日期和时间的类。它提供了操作和格式化日期、时间和日期时间组合的功能。QDataTime可以用于存储和检索日期和时间、比较日期和时间、对日期和时间执行算…

Mac删除自带的ABC输入法,简单快捷

一、下载PlistEdit Pro软件 二、终端执行 sudo open ~/Library/Preferences/com.apple.HIToolbox.plist 三、其中有一个数字下面的KeyboardLayout Name的value为“ABC”&#xff0c;这就是ABC输入法&#xff0c;点击上面的Delete按钮&#xff0c;删除整项ABC内容&#xff0c…

2023强网杯复现

强网先锋 SpeedUp 要求2的27次方的阶乘的逐位之和 在A244060 - OEIS 然后我们将4495662081进行sha256加密 就得到了flag flag{bbdee5c548fddfc76617c562952a3a3b03d423985c095521a8661d248fad3797} MISC easyfuzz 通过尝试输入字符串判断该程序对输入字符的验证规则为9…

01、全文检索 ------ 反向索引库 与 Lucene 的介绍

目录 全文检索 ------ 反向索引库 与 LuceneSQL模糊查询的问题反向索引库反向索引库的查询 Lucene&#xff08;全文检索技术&#xff09;Lucene能做什么Lucene存在的问题Solr 和 Elasticsearch 与 Lucene 的关系 全文检索 ------ 反向索引库 与 Lucene MySQL一些索引词汇解释 …

如何使用Docker部署JSON Crack

文章目录 1. 在Linux上使用Docker安装JSONCrack2. 安装Cpolar内网穿透工具3. 配置JSON Crack界面公网地址4. 远程访问 JSONCrack 界面5. 固定 JSONCrack公网地址 JSON Crack 是一款免费的开源数据可视化应用程序&#xff0c;能够将 JSON、YAML、XML、CSV 等数据格式可视化为交互…

2023年全国职业院校技能大赛(高职组)“云计算应用”赛项赛卷9

某企业根据自身业务需求&#xff0c;实施数字化转型&#xff0c;规划和建设数字化平台&#xff0c;平台聚焦“DevOps开发运维一体化”和“数据驱动产品开发”&#xff0c;拟采用开源OpenStack搭建企业内部私有云平台&#xff0c;开源Kubernetes搭建云原生服务平台&#xff0c;选…

【算法】Partitioning the Array(数论)

题目 Allen has an array a1,a2,…,an. For every positive integer k that is a divisor of n, Allen does the following: He partitions the array into n/k disjoint subarrays of length k. In other words, he partitions the array into the following subarrays: [a1,…

3 款最好的电脑硬盘数据迁移软件

您将从本页了解 3 款最好的 SSD硬盘数据迁移软件&#xff0c;磁盘供应商提供的软件和可靠的第三方软件。仔细阅读本文并做出您的选择。 什么是数据迁移&#xff1f; 数据迁移是将数据移动到其他计算机或存储设备的过程。在日常工作活动中&#xff0c;常见的数据迁移有三种&…

[Vue3] useRoute、useRouter

useRoute 返回当前路由地址。相当于在模板中使用 $route。必须在 setup() 中调用。用于在组件中获取当前路由的信息&#xff0c;返回一个包含路由信息的对象。这个函数适用于那些不需要监听路由变化的场景&#xff0c;只是获取当前路由信息的静态数据。 useRouter 返回 route…

[嵌入式系统-7]:龙芯1B 开发学习套件 -4- LoongIDE 集成开发工具的使用-创建应用程序工程、编译、下载、调试

目录 前言&#xff1a; 步骤1&#xff1a;设置工作工作空间 步骤2&#xff1a;设置工具链 步骤3&#xff1a;创建裸机应用程序 步骤4&#xff1a;创建带实时操作系统的应用程序 步骤5&#xff1a;编译 步骤6&#xff1a;下载调试 前言&#xff1a; LoongIDE集成开发环境…

ubuntu gedit主题更改

ubuntu16.04 gedit 编辑器又有首选项如何设置主题 这里下载主题 将主题XML复制到 /usr/share/gtksourceview-3.0/styles 文件夹内&#xff1b; 使用gsettings 命令设置喜欢的配色方案&#xff0c;使用方式如下&#xff1a;(实测不带.xml后缀哦) gsettings set org.gnome.gedi…

CleanMyMac X.4.14.6中文版新功能介绍,mac系统垃圾清理

近些年伴随着苹果生态的蓬勃发展&#xff0c;越来越多的用户开始尝试接触Mac电脑。然而很多人上手Mac后会发现&#xff0c;它的使用逻辑与Windows存在很多不同&#xff0c;而且随着使用时间的增加&#xff0c;一些奇奇怪怪的文件也会占据有限的磁盘空间&#xff0c;进而影响使用…