Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Blazor] IDisposable transient services are retained indefinitely #21652

Closed
mrpmorris opened this issue May 9, 2020 · 1 comment
Closed

[Blazor] IDisposable transient services are retained indefinitely #21652

mrpmorris opened this issue May 9, 2020 · 1 comment
Assignees
Labels
area-blazor Includes: Blazor, Razor Components Docs This issue tracks updating documentation Done This issue has been fixed feature-blazor-wasm This issue is related to and / or impacts Blazor WebAssembly

Comments

@mrpmorris
Copy link

mrpmorris commented May 9, 2020

REPO: https://github.com/mrpmorris/BlazorBug-21652

Any object that implements IDisposable is held onto by the dependency container. This means that if a class implements IDisposable and is registered as Transient, it will remain in the Blazor app scope forever.

Create a service.

  public class MyDisposableTransientService : IDisposable
  {
    public readonly static ConcurrentBag<WeakReference<MyDisposableTransientService>> Instances
      = new ConcurrentBag<WeakReference<MyDisposableTransientService>>();

    public MyDisposableTransientService()
    {
      Instances.Add(new WeakReference<MyDisposableTransientService>(this));
    }

    void IDisposable.Dispose()
    {
    }
  }

Register it as a transient dependency.

public void ConfigureServices(IServiceCollection services)
{
  ...(omitted for brevity)...
  services.AddTransient<MyDisposableTransientService>();
}

Change Index.razor

<ul>
  @foreach(var item in MyDisposableTransientService.Instances.ToArray())
  {
    <li>
      Alive = @item.TryGetTarget(out MyDisposableTransientService _)
    </li>
  }
</ul>


@code
{
	protected override void OnInitialized()
	{
		GC.Collect(int.MaxValue, GCCollectionMode.Forced);
	}
}
  1. Run the app
  2. Navigate between Index and Counter repeatedly

The above code demonstrates that references are held until the user's session ends, causing a memory leak.

To prove the reproduction code is not responsible for holding on to the references, simply remove the IDisposable implementation and re-run.

@javiercn javiercn added area-blazor Includes: Blazor, Razor Components feature-blazor-wasm This issue is related to and / or impacts Blazor WebAssembly labels May 9, 2020
@pranavkm pranavkm added this to the Next sprint planning milestone May 12, 2020
@mkArtakMSFT mkArtakMSFT added the Needs: Design This issue requires design work before implementating. label May 15, 2020
@mkArtakMSFT mkArtakMSFT added Docs This issue tracks updating documentation and removed Needs: Design This issue requires design work before implementating. labels Jun 1, 2020
@javiercn
Copy link
Member

Related doc topic here

@javiercn javiercn added the Done This issue has been fixed label Jun 12, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Jul 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components Docs This issue tracks updating documentation Done This issue has been fixed feature-blazor-wasm This issue is related to and / or impacts Blazor WebAssembly
Projects
None yet
Development

No branches or pull requests

4 participants