Search code examples
c#.netblockingsynchronousidisposable

Blocking in Dispose method


Can blocking in Dispose() method (synchronous variant) anyhow influence GC process?

Supposing:

  • classes with no explicit finalizers,
  • no real resource allocation/freeing within Dispose, just abusing the pattern to inject some code at the point of Dispose call
  1. Up to now, I understood Dispose as a "normal" method, which also could "accidentally" be called by compiler generated code from some syntactic sugar constructs, like using (var i = new Something(...)){} or using var i = new Something(...) and if using is not suitable for us (from any reason), we just call it directly;
  2. This implies, any blocking operation inside means only delay at the point of Dispose execution, right?
  3. This implies, GC does not care about Dispose at all and just collects any instance, when there are no references to it, regardless of Dispose being called or not, right?
  4. From above I imply that under mentioned conditions, there is no reason for any memory leak nor GC influence, when working with instances blocking in Dispose, right?

Example of such class:

class DisposeBlocker : IDisposable
{
    private Task localWork;
    private Task remoteWork;
    ...
    DisposeBlocker(Task work)
    {
        remoteWork = work;
    }

    void Dispose()
    {
        for (var i = 0; i < 1000000; ++i) {} // CPU Bound
        Thread.Sleep(1000); // Should be ok too, right?
        Task.Delay(1000).GetAwaiter().GetResult(); // Is this still ok? Thread pools, contexts, similar stuff...
        Task.WhenAll(localWork, remoteWork).GetAwaiter().GetResult(); // Same as the previous one, right?
    }
}

Solution

  • Correct.

    If it has no finalizer, GC will not care about the Dispose method.

    This sounds like a big code smell, though: if Dispose is necessary, I would imagine it would be desirable to ensure it is called in most cicumstances, ergo you need a finalizer. And finalizers MUST NOT BLOCK or throw an exception under any circumstances.

    It's also unexpected for Dispose to block either. So you really should avoid this kind of setup.