C#垃圾回收的优化实践

 更新时间:2025年06月11日 09:51:41   作者:ghost143  
垃圾回收是.NET的自动内存管理机制,通过分代收集和内存压缩优化内存使用,本文主要介绍了C#垃圾回收的优化实践,需要的朋友们下面随着小编来一起学习学习吧

什么是垃圾回收?

  • 定义:垃圾回收是一种自动内存管理机制,负责回收不再使用的对象所占用的内存。
  • 目的:通过自动化内存回收,减少内存泄漏的风险,并简化开发者的工作。

垃圾回收的核心概念 

1. 垃圾回收器的工作原理

  • .NET垃圾回收器(GC)跟踪对象的使用情况,并在对象不再被引用时回收其内存。
  • 采用标记-清除算法来识别不再使用的对象。

2. 分代收集 

 代0(Generation 0):

  • 包含新创建的对象。
  • 回收频率最高,旨在高效回收临时对象。

代1(Generation 1):

  • 作为短期对象和长期对象之间的“中间地带”。
  • 当代0满时,代1会参与回收。

代2(Generation 2):

  • 包含生命周期较长的对象,如静态和全局变量。
  • 回收频率最低。

 3. 内存压缩

  • 在代0和代1回收后,GC会移动存活对象以填补空闲空间,减少碎片并优化内存布局。
  • 代2的内存压缩只有在极少数情况下才会进行,因为这些对象通常生存时间较长。

工作流程 

标记阶段:

标识所有活动的对象(即仍然被引用的对象)。

清除阶段:

收集未标记的对象,并释放它们所占用的内存。

压缩阶段(可选):

移动存活对象,使得内存更加紧凑,通常在代0和代1进行。

使用垃圾回收的最佳实践 

1. 销毁模式和IDisposable接口

  • 实现 IDisposable 接口以手动管理非托管资源的生命周期。
  • 确保资源及时释放,减少垃圾回收负担。
public class ResourceHolder : IDisposable
{
    private bool disposed = false;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // 释放托管资源
            }
            // 释放非托管资源
            disposed = true;
        }
    }

    ~ResourceHolder()
    {
        Dispose(false);
    }
}

2. 使用 using 语句

对于实现了 IDisposable 接口的对象,使用 using 语句可以确保自动调用 Dispose() 方法。

using (var resource = new ResourceHolder())
{
    // 使用资源
}

3.手动触发 GC(仅在必要时)

虽通常不建议手动调用,但在特定场合(如执行大量内存操作后)可使用 GC.Collect() 触发。

GC.Collect();
GC.WaitForPendingFinalizers();

使用场景

实时应用:

例如游戏或多媒体应用,通过有效管理内存提升响应速度。

服务器端应用:

在Web服务器或API服务中,确保内存管理高效以支持大量并发请求。

桌面应用:

对大规模数据处理软件来说,良好的内存管理有助于维持系统稳定性。

实践习题 

编写一个程序,通过创建大量短生命周期对象来观察垃圾回收的工作过程。使用GC.GetTotalMemory()方法查看内存使用情况。

using System;

class Program
{
    static void Main()
    {
        long memoryBefore = GC.GetTotalMemory(false);
        Console.WriteLine($"Memory before allocation: {memoryBefore}");

        CreateObjects(100000);

        GC.Collect(); // 手动触发垃圾回收
        GC.WaitForPendingFinalizers();

        long memoryAfter = GC.GetTotalMemory(false);
        Console.WriteLine($"Memory after garbage collection: {memoryAfter}");
    }

    static void CreateObjects(int count)
    {
        for (int i = 0; i < count; i++)
        {
            var obj = new object();
        }
    }
}

说明:

  • CreateObjects 方法在循环中创建大量对象。
  • 使用GC.GetTotalMemory(false)获取当前内存使用情况。
  • 利用GC.Collect()手动触发垃圾回收并观察内存变化。

这些例子展示了如何实现资源管理和内存监控,帮助您更好地理解.NET中的垃圾回收机制

到此这篇关于C#垃圾回收的优化实践的文章就介绍到这了,更多相关C#垃圾回收内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入探讨C#中的const、readonly关键字

    深入探讨C#中的const、readonly关键字

    这篇文章主要介绍了深入探讨C#中的const、readonly关键字,本文可以帮助你深刻理解这两个关键字,而且是面试中最可能面试到的问题哦,需要的朋友可以参考下
    2014-08-08
  • C#实现微信结合百度api获取当前用户地理位置的方法

    C#实现微信结合百度api获取当前用户地理位置的方法

    这篇文章主要介绍了C#实现微信结合百度api获取当前用户地理位置的方法,结合实例形式分析了C#调用微信与百度API接口的相关操作技巧,需要的朋友可以参考下
    2017-07-07
  • C#编程读取文档Doc、Docx及Pdf内容的方法

    C#编程读取文档Doc、Docx及Pdf内容的方法

    这篇文章主要介绍了C#编程读取文档Doc、Docx及Pdf内容的方法,涉及C#操作COM组件读取Doc、Docx及Pdf文档的相关技巧,需要的朋友可以参考下
    2015-05-05
  • C#实现控制台飞行棋小游戏

    C#实现控制台飞行棋小游戏

    这篇文章主要为大家详细介绍了C#实现控制台飞行棋小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下的相关资料
    2021-07-07
  • C#调用打印机实现打印

    C#调用打印机实现打印

    这篇文章介绍了C#调用打印机实现打印的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • C# 泛型参数转换

    C# 泛型参数转换

    本文介绍了C# 泛型参数转换的相关知识,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • C#数组的常用操作方法小结

    C#数组的常用操作方法小结

    Array数组在C#中同样是最基本的数据结构,下面为大家C#数组的常用操作方法小结,皆为细小的代码段,欢迎收看收藏
    2016-05-05
  • C# WinForm捕获未处理的异常实例解析

    C# WinForm捕获未处理的异常实例解析

    这篇文章主要介绍了C# WinForm捕获未处理的异常,包括了常见的未捕获的异常、UI线程异常、非UI线程异常等,非常实用,需要的朋友可以参考下
    2014-09-09
  • c#使用IAsyncEnumerable实现流式分段传输

    c#使用IAsyncEnumerable实现流式分段传输

    这篇文章主要为大家详细介绍了c#如何使用IAsyncEnumerable实现流式分段传输,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-10-10
  • 深入探讨C#中的结构struct

    深入探讨C#中的结构struct

    这篇文章详细介绍了C#中的结构struct,有需要的朋友可以参考一下
    2013-09-09

最新评论