当前位置: 首页 > article >正文

【C#】垃圾回收

C# 语言运行在 .NET 框架上,该框架使用了一种称为垃圾回收(Garbage Collection, GC)的自动内存管理机制。垃圾回收的主要目的是自动化地管理和释放不再使用的对象所占用的内存,从而简化编程模型,并减少由于手动内存管理不当导致的错误。

1. 垃圾回收的工作原理

.NET 的垃圾回收器是基于分代收集理论设计的,它将托管堆中的对象分为三个代:0 代、1 代和 2 代。新创建的对象首先被放入 0 代区域。如果一个对象经过一次完整的垃圾回收后仍然存活,则会被移动到 1 代;同样地,如果在 1 代中再次存活下来,它将被移动到 2 代。这样的设计基于一个观察,即大部分对象的生命周期都非常短,而长期存在的对象相对较少。

  • 0 代:这是最年轻的对象集合,包含最近分配的对象。
  • 1 代:这个集合包含了从 0 代晋升过来的对象,这些对象已经至少存活过一次完整的垃圾回收周期。
  • 2 代:这是最老的一代,包含那些经历了多次垃圾回收周期依然存活的对象。

垃圾回收器会定期检查各个代中的对象,并移除那些不再被任何活动根引用的对象。根可以是全局变量、局部变量、CPU 寄存器等。当垃圾回收发生时,它通常会先从较年轻的一代开始清理,因为那里有更高的机会找到可回收的对象。

2. 强制垃圾回收

虽然 .NET 提供了 GC.Collect() 方法来强制执行垃圾回收,但这种做法通常是不推荐的。原因如下:

  • 性能影响:强制垃圾回收会导致程序暂停以进行垃圾回收操作,这可能会显著影响应用程序的响应性和整体性能。
  • 干扰正常行为:垃圾回收器有自己的算法来决定何时进行垃圾回收,强制回收可能会打乱这一过程,使得垃圾回收器不能按照最优的方式工作。
  • 不可预测性:即使调用了 GC.Collect(),也不能保证所有不再需要的对象都会立即被回收,因为某些对象可能还在终结过程中或者存在其他复杂的情况。

3. 使用场景

尽管如此,在一些特定情况下,比如单元测试或确保资源被释放之前结束应用程序时,开发者可能会选择使用 GC.Collect()GC.WaitForPendingFinalizers() 来帮助验证资源是否已被正确释放。但在生产环境中,应该尽量避免这样做。

总之,.NET 的垃圾回收系统旨在为开发人员提供便利并提高安全性,大多数时候让垃圾回收器自动处理内存是最理想的做法。只有在非常特殊的情况下,才应考虑干预垃圾回收过程。

 

4.GC.SuppressFinalize(this)GC.Collect() 和 GC.WaitForPendingFinalizers()

4.1 用途和效果

  1. GC.SuppressFinalize(this)

    • 该方法用于告诉垃圾收集器不要调用当前对象的终结器(finalizer)。通常在实现了 IDisposable 接口的对象中使用,在调用了 Dispose 方法并正确释放了所有非托管资源后,可以调用此方法来避免终结器的开销。如果对象没有实现终结器或终结器已经被抑制,则调用这个方法没有任何影响。
    • 当确定已经手动清理了所有需要清理的资源时,可以使用它来优化性能,因为终结器会延迟对象的最终回收时间。
  2. GC.Collect()

    • 该方法强制垃圾收集器立即执行一次完整的垃圾回收操作。这包括回收不再被引用的所有对象,并可能涉及多个代(generations)的内存区域。一般情况下不推荐频繁调用此方法,因为它可能导致应用程序暂时冻结,同时也会干扰垃圾收集器的正常工作流程。
    • 在某些特定场景下,比如测试环境中为了观察垃圾回收行为,或者当程序结束前确保所有对象都被回收,可能会用到它。
  3. GC.WaitForPendingFinalizers()

    • 该方法会阻塞当前线程,直到所有待处理的终结器都已完成执行。这意味着如果有任何对象的终结器正在运行或等待运行,那么调用此方法的线程将会暂停,直到这些终结器全部完成。
    • 它常用于确保在继续执行之前所有的终结逻辑都已经处理完毕,尤其是在需要保证资源完全释放的情况下。

4.2 组合使用

理论上来说,这三个方法是可以组合使用的,但具体是否合适取决于实际应用场景:

  • 如果想要立即回收一些对象,并且确保那些有终结器的对象也完成了它们的清理工作,可以先调用 GC.Collect() 强制进行垃圾回收,然后使用 GC.WaitForPendingFinalizers() 等待所有终结器完成。
  • 而 GC.SuppressFinalize(this); 通常是针对单个对象实例使用的,如果确定某个对象不需要通过其终结器来清理资源,可以在适当的地方(如 Dispose 方法内)调用它。

然而,需要注意的是,除非确实存在明确的需求,否则不应该轻易地主动干预垃圾收集过程,因为这可能会对程序性能产生负面影响。在大多数情况下,让.NET框架的垃圾收集机制自动管理内存是最优的选择。

 


http://www.kler.cn/news/317448.html

相关文章:

  • 项目总结,路径匹配的业务逻辑
  • Docker使用指南
  • HTML常用的文本标签
  • Docker + Win 10 学习记录
  • OpenAI GPT o1技术报告阅读(3)-英文阅读及理解
  • 828华为云征文 | 云服务器Flexus X实例:RAG 开源项目 FastGPT 部署,玩转大模型
  • 数据结构-C语言实现线性表的顺序存储结构
  • Python Web日志管理与监控实践指南
  • OpenCV特征检测(12)检测图像中的潜在角点函数preCornerDetect()的使用
  • 使用ffmpeg实现音视频文件格式转换
  • C语言从头学62——学习头文件stdlib.h(一)
  • 如何通过蜂巢(容器安全)管理内部部署数据安全产品与云数据安全产品?
  • 【Android】 IconFont的使用
  • 一体化运维监控管理平台的全面监控能力
  • 使用Hutool-poi封装Apache POI进行Excel的上传与下载
  • 单线服务器是什么?单线服务器有什么优点?
  • 掌握 Flutter 中的 `Overlay` 和 `OverlayEntry`:弹窗管理的艺术
  • 如何将Vue项目部署至 nginx
  • 力扣最热一百题——最小覆盖子串
  • 【优选算法之前缀和】No.6--- 经典前缀和算法
  • Unity webgl跨域问题 unity使用nginx设置跨域 ,修改请求头
  • 基于微信小程序的宠物寄养平台的设计与实现+ssm(lw+演示+源码+运行)
  • Adams与Matlab通过FMI联合仿真
  • 我的AI工具箱Tauri版-FunAsr音频转文本
  • git 删除 git push 失败的记录
  • 阿里开源多模态大模型Ovis1.6,重塑出海电商AI格局
  • python自学笔记
  • 价格便宜又好用的云电脑挑选:ToDesk云电脑 vs 青椒云
  • oracle rac多个实例就相当于多个数据库系统程序
  • Python 管理 AWS ElastiCache 告警