You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

.NET Framework与.NET Core中System.Windows.Forms.WebBrowser垃圾回收差异及内存泄漏问题求助

.NET Framework与.NET Core中System.Windows.Forms.WebBrowser垃圾回收差异及内存泄漏问题求助

我目前正在将团队的应用从.NET Framework迁移到.NET Core,过程中遇到了一个棘手的内存泄漏问题,想请大家帮忙分析下。

问题核心现象

我们自定义的ZWebBrowser(继承自System.Windows.Forms.WebBrowser)在.NET Core环境下无法被垃圾回收器正确回收。通过内存dump分析发现,底层的COM对象(也就是WebBrowser依赖的微软ActiveX控件)持有了WebBrowserSiteWebBrowserEvent强引用,导致对象一直无法被释放。对比.NET Framework和.NET Core的内存dump能看到明显差异(抱歉截图质量不佳,但能看到Weak引用前的RefCounted handle表现不同)。

我尝试过的解决方法

为了手动释放COM对象,我重写了ZWebBrowserDispose方法,尝试获取ActiveXInstance并调用Marshal.FinalReleaseComObject,但完全没有效果:

protected override void Dispose(bool disposing)
{
    object? comObj = null;
    if (disposing)
    {
        comObj = this.ActiveXInstance;
    }
    base.Dispose(disposing);
    if (comObj is object && Marshal.IsComObject(comObj))
    {
        Marshal.FinalReleaseComObject(comObj);
    }
}

进一步的测试验证

为了明确差异,我写了一个简单的测试用例:循环创建100个WebBrowser对象并放入using语句块中,用弱引用跟踪它们的存活状态。结果完全不同:

  • .NET Core环境下,100个对象全部被保留
  • .NET Framework环境下,只保留最后一个对象

测试代码如下:

public void TestRunLeak()
{
    List<WeakReference> browsers = new List<WeakReference>();
    for (int i = 0; i < 100; i++)
    {
        using (var browser = new System.Windows.Forms.WebBrowser())
        {
            browsers.Add(new WeakReference(browser));
            browser.Navigate("about:blank");
        }
    }
    var count = browsers.Count(browser => browser.IsAlive);
#if NETFRAMEWORK
    Assert.That(1, count); // .NET Framework下count == 1,仅最后一个对象存活
#elif NETCOREAPP
    AssertEquals(100, count); // .NET Core下count == 100,所有对象都未被回收
#endif
}

我的疑惑

现在我最想搞清楚的是:.NET Core和.NET Framework的GC机制在处理WebBrowser这类依赖COM组件的对象时,到底有什么核心差异?为什么两者的垃圾回收行为会出现这么大的区别?希望有了解这部分底层逻辑的朋友能帮忙解惑,或者给我一些排查、解决这个泄漏问题的思路。


内容来源于stack exchange

火山引擎 最新活动