'WinForms Form is never garbage collected due to reference from ServiceScope

I have a WinForms Form(s) that is not always garbage collected. The form loads quite a bit of data and when it is not garbage collected, it can cause a significant memory leak. This is how I instantiate the form:

// RootForm.cs
private void CreateFormInScope<T>() where T : Form
{
  var scope = _serviceProvider.CreateScope();
  var form = scope.ServiceProvider.GetRequiredService<T>();
  form.FormClosed += (_, _) => scope.Dispose();
  form.MdiParent = this;
  form.Show();
}

After failing to get anywhere with Visual Studio's diagnostic tools, I tried dotnet dump. I used dumpheap -type [TYPENAME] and then used gcroot on one of the addresses. Here's the end of the root shown:

-> 00000170022A7598 Microsoft.EntityFrameworkCore.Infrastructure.CoreOptionsExtension
-> 00000170022A1610 Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope
-> 00000170022EA2C0 System.Collections.Generic.List`1[[System.Object, System.Private.CoreLib]]
-> 0000017002BBDD50 System.Object[]
-> 00000170022EF580 FunctionScreens.ProductForm

OK, a scope is holding a reference to the ProductForm. The only scope that could have a reference to it is the child scope I created, right? But that child scope was a local variable, so it shouldn't be referenced by anything, let alone EF Core.

The leak does seem to occur more often if I close the window before async operations are complete, but I do catch all the exceptions in the event handlers to prevent them from propagating.

Any ideas why it is not being GCed or what I could do to track it down?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source