You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何在GC启动时触发事件?能否规避GC暂停影响?

关于C#垃圾回收(GC)的两个问题解答

一、能否在GC启动时触发事件?如何实现?

可以实现,但你设想的轮询Gc.IsWorking()的方式不可行——.NET中根本不存在GC.IsWorking()这个API,而且轮询不仅效率低下,还可能错过GC启动的精确时机。

官方提供了更可靠的方案:

  • 使用GC.RegisterForFullGCNotification注册全量GC的通知,结合GC.WaitForFullGCApproach和GC.WaitForFullGCComplete方法监听GC的启动与完成。
  • 在.NET Core 3.0及以上版本,还可使用GC.RegisterNoGCRegionCallback等回调,但主要针对NoGC区域的场景。

以下是全量GC通知的示例代码:

using System;
using System.Threading;

class GCNotificationExample
{
    static void Main()
    {
        // 注册全量GC通知,设置阈值参数
        GC.RegisterForFullGCNotification(10, 10);

        // 启动独立监听线程
        Thread listenerThread = new Thread(ListenForGC);
        listenerThread.IsBackground = true;
        listenerThread.Start();

        // 模拟内存分配,触发GC
        for (int i = 0; i < 10000; i++)
        {
            _ = new byte[1024 * 1024];
            Thread.Sleep(10);
        }
    }

    static void ListenForGC()
    {
        while (true)
        {
            // 等待GC即将启动的通知
            GCNotificationStatus status = GC.WaitForFullGCApproach();
            if (status == GCNotificationStatus.Succeeded)
            {
                Console.WriteLine("GC即将启动,执行预处理逻辑");
                // 此处添加你需要触发的代码
            }
            else if (status == GCNotificationStatus.Canceled)
            {
                break;
            }

            // 等待GC完成的通知
            status = GC.WaitForFullGCComplete();
            if (status == GCNotificationStatus.Succeeded)
            {
                Console.WriteLine("GC已完成,执行后处理逻辑");
                // 此处添加GC完成后的代码
            }
            else if (status == GCNotificationStatus.Canceled)
            {
                break;
            }
        }
    }
}

注意:该方案仅针对全量GC,增量GC或后台GC的通知目前没有直接的官方API支持。

二、能否通过unsafe等方式让部分代码不受GC暂停影响?

首先明确:GC触发时的暂停(STW,Stop-the-World)会挂起所有托管线程,不管是否使用unsafe代码——unsafe只是允许你操作指针,但线程本身还是托管线程,依然会被GC挂起。

想要避免GC暂停影响,只有两种可行方向:

  1. 使用非托管线程执行非托管代码:非托管线程(比如通过P/Invoke调用Win32 API创建的线程)不会被.NET GC挂起,在这些线程中运行的非托管代码可以不受GC暂停影响。但需要注意托管与非托管代码的交互边界,避免内存泄漏。
  2. 利用GC的并发/后台回收模式:在服务器GC模式下,.NET支持后台回收,此时大部分回收工作在后台线程进行,暂停时间会大幅缩短,但依然存在短暂的暂停(比如标记阶段的最终暂停)。你可以通过配置gcServer=true启用服务器GC,或通过GCSettings.LatencyMode设置低延迟模式(比如GCLatencyMode.LowLatency)来减少暂停频率,但无法完全消除。

unsafe代码本身无法规避GC暂停,因为它依然运行在托管线程上,GC挂起托管线程的逻辑与代码是否unsafe无关。

内容的提问来源于stack exchange,提问作者AliSalehi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 08:06:29