Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IServiceProvider garbage collection / disposal

I was trying to debug a memory leak in my app (see related question) and have encountered a smilingly wrong behavior.

In this code (simplified snippet, of course):

    while (true)
    {
        using (var context = _serviceProvider.GetRequiredService<IDataContext>())
        {
            Console.WriteLine("Hello");
        }
    }

Memory consumption grows rapidly.

If I comment out service spawn, memory consumption is stable.

    while (true)
    {
        // using (var context = _serviceProvider.GetRequiredService<IDataContext>())
        // {
            Console.WriteLine("Hello");
        // }
    }

Service was registered as transient.

My understanding is that using statement is responsible for disposing a service. var context is created in the scope of while and should be destroyed when new iteration begins.

My first thought was that GC just does not do its job frequently enough, but does not frequency increase when amount of consumed memory increases?

Why am I wrong?

like image 749
Dmytro Bogatov Avatar asked Apr 06 '17 01:04

Dmytro Bogatov


People also ask

How do you override a Dispose method in C#?

These classes need to dispose of these objects. I created a virtual Dispose method in the base ScreenObject base class and then implemented an override Dispose method in each of the derived classes that hold onto unmanaged resources.

Is Dispose called automatically C#?

Dispose() will not be called automatically. If there is a finalizer it will be called automatically. Implementing IDisposable provides a way for users of your class to release resources early, instead of waiting for the garbage collector.

When Dispose method is called in C#?

When the close brace is reached, the Dispose( ) method will be called on the object automatically, as illustrated in Example 4-6. In the first part of this example, the Font object is created within the using statement. When the using statement ends, Dispose( ) is called on the Font object.

How do you Dispose of a class object in VB net?

Calling Dispose on the class will cause it to notify the file system that it no longer needs the file, and it may thus be made available to other entities. In general, if an object which implements IDisposable is abandoned without calling Dispose , some things which should get done, won't be. There is a mechanism in .


1 Answers

After days of fighting the problem, I finally derived the answer. In short, the issue is that Microsoft DI container does not dispose transient services, it keeps references on them.

Here is the corresponding issue on github.

The developers do not plan to fix it since the cost (complexity and hackiness) of fixing overweighs the benefits.

Suggested workaround is using scoped service instead of the transient one.

Here is an example code, see more in issue.

using (var scope = serviceProvider.CreateScope())
using (var context = scope.ServiceProvider.GetRequiredService<IDataContext>())
{ ... }
like image 65
Dmytro Bogatov Avatar answered Oct 31 '22 23:10

Dmytro Bogatov