.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控件)持有了WebBrowserSite和WebBrowserEvent的强引用,导致对象一直无法被释放。对比.NET Framework和.NET Core的内存dump能看到明显差异(抱歉截图质量不佳,但能看到Weak引用前的RefCounted handle表现不同)。
我尝试过的解决方法
为了手动释放COM对象,我重写了ZWebBrowser的Dispose方法,尝试获取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




