Skip to content

IServiceScope.Dispose() and DisposeAsync() should not stop disposing other services if one throws an exception #113563

Description

@mohammadKhalafi

Currently, in .NET, when using IServiceScope, if multiple services registered in the scope implement IDisposable or IAsyncDisposable, an exception in Dispose() or DisposeAsync() prevents the remaining services from being disposed when the scope is being disposed.

This can lead to memory leaks and unreleased resources

Activity

  1. dotnet-policy-service commented on Mar 15, 2025

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @dotnet/area-extensions-dependencyinjection
    See info in area-owners.md if you want to be subscribed.

  2. KalleOlaviNiemitalo commented on Mar 16, 2025

    @KalleOlaviNiemitalo

    IDisposable.Dispose() should not throw exceptions, according to CA1065: Do not raise exceptions in unexpected locations. Windows Communication Foundation (WCF) is known to violate this, though.

    If service A depends on service B, and A.Dispose() throws but B.Dispose() is then called, it might cause problems later if A continues to use B. For example, B rents memory from a pool, A starts an asynchronous operation that writes to the memory, A.Dispose() fails to abort the operation, B.Dispose() returns the memory to the pool, and C rents the same memory while the operation started by A is still writing to it. For that reason, I think M.E.DI should not be changed to continue disposal of services after the first exception, by default; but an opt-in feature would be possible. If the opt-in were in ServiceProviderOptions, it would not need to be supported in other IServiceProvider implementations.

  3. julealgon commented on Mar 17, 2025

    @julealgon

    @mohammadKhalafi can't you create a decorator for your problematic type that wraps Dispose in a try/catch block?

    I would hate to see a framework/extensions class be updated to accomodate such a bad practice, as it would basically indirectly encourage its use.

  4. steveharter commented on Mar 24, 2025

    @steveharter
    Contributor

    I think an opt-in option makes sense, however it is low-priority at this time since it has not been requested in the past, at least based on some simple searches.

    Moving to future to gauge interest \ feasibility.

  5. added this to the Future milestone on Mar 24, 2025
  6. added
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    and removed
    untriagedNew issue has not been triaged by the area owner
    on Mar 24, 2025
  7. mohammadKhalafi commented on Mar 24, 2025

    @mohammadKhalafi
    Author

    @julealgon
    @steveharter

    I think it's actually a good thing for the framework to provide an escape hatch for cases where a bad practice exists in an application—especially when it might come from an external library.

    At the very least, when creating a scope, there could be an option that gives full control over disposal to the user. This way, disposal of the scope wouldn’t automatically dispose of all the disposables resolved from it, allowing users to manage disposal as they see fit.

  8. KalleOlaviNiemitalo commented on Mar 25, 2025

    @KalleOlaviNiemitalo

    I imagine M.E.DI would define some interface IDisposableTracker : IDisposable { void Add(IDisposable); } and let the application provide an instance of that; then the container would add disposable services to that as it creates them. Disposing the IServiceScope would dispose the IDisposeTracker, and that would be responsible of disposing the services and handling exceptions.

    Unclear about this scheme:

    • How does the application provide the IDisposableTracker: is it a parameter of CreateScope or a property of ServiceProviderOptions, or can it be registered as a service itself? In the latter case, can other services be injected to it?
    • If one later wants to extend this so that the IDisposableTracker is also given some information from the ServiceDescriptor (especially ServiceType and ServiceKey), how does one do that without breaking the API?
    • What happens if IDisposableTracker.Add calls back to the IServiceProvider, requesting another service from there?
    • If IDisposableTracker.Add throws an exception, how is that handled? Does it cause M.E.DI to immediately dispose the service that could not be added?
  9. modified the milestones: Future, 11.0.0 on Feb 27, 2026
  10. locked and limited conversation to collaborators on Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions