How does the . NET "using" and Garbage interface work?

Asked

Viewed 219 times

6

In a reply now deleted here on the site it seems that there was some confusion with the content indicating the use of GC.Collect() and how the using C# works. So how does it actually work using and what its relation to . NET’s GC?

The using really frees operating system resources?

What are these features? Is memory?

It is the GC that releases these resources?

When in fact these resources are released, at the end of the block using or when the GC is invoked? Does it make a difference to manually invoke or let it be invoked? Have a concept of making the release as soon as possible.

Why the using exists if the GC is that it takes care of?

What happens if you don’t use the using correctly?

If using it correctly has as the resource not be released? IE, it may be that the resource is released only after?

In discussion there it was stated that in the author’s work had resources which were not immediately released. When does this happen? It is possible that liberation is not immediate in some situation?

All memory is released when releasing the resource?

There it was stated that the GC will release the resources because it has already been warned that the object is no longer in use. But the GC (at least the tracing) does not exist precisely to determine whether the object is in use or not and does not need to be warned? This is confusing.

The using in fact gives some warning or communicates with the GC to indicate that it must release these resources?

There’s nothing in the Dispose() communicating with the AG?

Documentation is always right?

And finally, I must call GC.Collect() manually? When? What happens bad if I call? Why does the method exist if I shouldn’t call you?

The more details the better, to be clear.

  • The reason I posted this is that there was a lot of discussion about it right after I gave it away feedback (then there are people who complain that they do not receive when they take negative), and I needed to explain in detail all the errors found there. I suggested that a new question be asked to better understand the mistake but I knew that this would not happen because of the attitude of considering that there was no mistake.

  • You knew it would come negative, you’ll always have someone who takes advantage. I prefer to receive negatives, contrary to what some think I do not care about reputation but rather about correct answers and I am proud of them and of all my achievements. I don’t think it’s fair that other people have a wrong answer and nothing is said. I also posted because I was advised not to argue, "put a llink that shows error and good". Note that it is not the case to argue, of difference of interpretation, there was a clear mistake there and I try to help people know how it really works.

1 answer

5


The question is best understood with the context of the deleted answer and the discussion that took place there.

In a reply now deleted here on the site it seems that there was some confusion with the content indicating the use of GC.Collect() and how the using of C# works. So how does it actually work using and what relationship it has with . NET’s GC?

In essence no relationship, except the fact that the using was created to prevent GC from needing to be called. Noted the opposition?

The . NET GC is tracing and so it is not deterministic, that is, you do not know when it will run, unless you call manually, but you should not call it (see below). Some types of resources (I’ll talk later) need to be deterministically released and so you need a mechanism that does this in the code without having to invoke GC in any way.

The using frees resources, GC frees memory, this will be clarified soon.

The using really frees operating system resources?

Yes, in some cases. In fact it is common that these resources are provided by the operating system, but there are several other ways to get and have to release these resources that are not from the operating system, can be from any external service, for example database, very common.

It may even have objects that do not directly access external resources. If it accesses indirectly it is likely that it will need to have that same pattern Disposable Pattern that the using uses, is viral.

It is very common to see here on the site people creating classes to manage connection, and how the connection needs to be dropped (call the Dispose(), probably with the using) the object that holds this connection needs to be Disposable also (need to implement the interface correctly IDisposable), but many do not. We see this directly, probably people saw wrong somewhere and learn so. This is one of the reasons that leaks so much appeal around.

Although it is common that these resources are derived from the operating system there are several cases that are not, it cannot be stated that they are only from the OS.

What are these features? Is memory?

Feature is something your application cannot manage, it is not managed memory, so it is not memory that the Garbage Collector takes care, it is exactly the opposite, if this resource has some memory allocation it is managed by itself, the resource is that takes care of it, and releases when the resource finds it best, it is his problem, the GC will never interfere with it, he has no notion of that memory (it’s not that simple, but we don’t want to complicate).

One of the things that many do not understand is that this release may involve nothing memory, managed or not. It could be to put out a lamp and nothing else, this liberation is to finish something, is to determine that it is closing that, which will no longer operate there.

This has already been answered in more detail at What types of resources are released in a "using statement"?.

See also: Memory Leak in Xmlserializer.

And yet: Dispose method().

There may be confusion there when the author says that he did not release the resource, he may be saying that he did not release the object that controlled the resource and thinks that the resource is still there available (it may even be dangerous to try to access a resource for an object that is buzzing)

It is the GC that releases these resources?

No, never. This release only occurs by invoking your code, although in some cases implicitly. The most common implicit form is through using. The using will call the method Dispose() and this will call whatever is necessary to release the resource. It is very common that the method to be called is a Close() or something like that. And this Close() call the operating system API, database or other service that provided the feature. True release is feature problem, you call an API function that says you don’t need it anymore, that’s all, the API fires the rest it needs to do.

We talk about releasing resources because in most cases when calling this function actually begins the release process, but there are no guarantees that this will occur on time. So you’re thinking he’ll be released later and you should worry, right? No, it’s not your concern, your application doesn’t need to do anything else, the resource turns, it will release if it was well done, and what people actually use were well done, it will only give a problem if it is something done by a naive person and without ability to do that.

Please do not misunderstand, the release occurs on time in almost every case, and if you have any that does not happen it makes no difference to your application, for all the effects for your application has been released. The . NET does not care about this at any time. I am talking like this to be absolutely correct, even pedantic, but in a simplified way we can say that the resource is always released on time.

When in fact these resources are released, at the end of the block using or when GC is invoked? It makes a difference to manually invoke or let it be invoked? It has a concept of making liberation like this as possible.

At the end of the using always! (by the way in C# 8 no longer needs the block it is possible to declare the variable with an attribute using and the release will occur at the end of the current block, no need to create a block only for the using. Nothing has changed in semantics, only in syntax. So:

void Metodo() {
    using var http = new HttpClient();
    http.......
    ...
} // o recurso da variável http será liberado aqui

The using is actually transformed into something like this:

{
    HttpClient http = new HttpClient();
    try {
       // Algum código...
    } finally {
        if (http != null)
            ((IDisposable)http).Dispose();
    }
}

One curious thing is that just the HttpClient used to make a kind of pool, then this release is just to say that a member of the pool becomes available, but there is no release for the operating system, unless the internal algorithm thinks it should release. So you have to be careful because the terminology used is usually a simplification of what actually happens.

In fact everyone uses HttpClient wrong, I used it myself and didn’t know everything, because I trusted that the documentation had everything I needed, but I learned the lesson.

As curiosity of how is the Dispose() of this class:

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if (disposing && !_disposed)
    {
        _disposed = true;

        if (_disposeHandler)
        {
            _handler.Dispose();
        }
    }
}

The class HTTPClient has no destructor, so "the feature" of it will not be claimed if you do not use right, but I will show from another class:

~FileStream()
{
    // Preserved for compatibility since FileStream has defined a
    // finalizer in past releases and derived classes may depend
    // on Dispose(false) call.
    Dispose(false);
}

I put in the Github for future reference.

Why the using exists if the GC is that it takes care of?

Precisely because it does not take care of the same thing. This is one of the errors of the answer there.

The using takes care of the resource, something external, something . NET has no control over, something that needs to end deterministically and... immediately. GC takes care of the memory of . NET, of its application, it takes care of the object that will be created to access the resource, but it is different from the resource itself. It’s an object that makes a wrap in the resource, it is he who has methods and some fields to control access to the resource. The resource is another separate object in memory not managed by GC and that all . NET does not understand how to handle it.

What happens if you don’t use the using correctly?

The feature is not released on time deterministically. This is not the end of the world in some cases, but can create problems for the application. I have seen many cases of slowness, excessive memory consumption and even blocking access to the resource that should have been finished but is still active at some point.

Here comes the GC. When the GC collects objects no longer used by the application it calls a method ~Classe() (every object has this method because it is a destructor (flame also Finalize() but I will not detail to not confuse more). In many cases he does nothing, but where there is a Dispose() he has almost an obligation to call the Dispose() so if the using is not used correctly yet at some point can be that the resource is released, and this time is when the object that controls the resource can be released by the GC. It is a matter of dependency, if the object is no longer used and the GC is authorized to destroy it it needs to ensure that anything attached to it is released together, otherwise this feature would hang and leak.

You could say that every time a Dispose() is executed through the destructor and not the using there’s something wrong with your code and it needs fixing. It’s full of code like that around.

Use the using correctly does not resolve all types of leakage.

I talk a lot about using but of course the Dispose() can be called deterministic manually in your code, only you should not do this because you will probably do it wrong, there is a right way to do, the design pattern of the using is there for you not to make a mistake, you just need to use it in the right place. There is plenty of content on the site about this.

If using it correctly has as the resource not be released? IE, it may be that the feature is released only after?

In this condition this never occurs. If the resource ends up being released later it is because the using is wrong, probably not even where it should.

In discussion there it was stated that in the author’s work had resources that were not released immediately. When does this happen? It is possible release not to be immediate in any situation?

I’m sorry that the code he’s working on has those problems. There are two ways, start studying the subject more and fix the problem or live with the error forever, or until someone comes and fixes it. I’ve already been called to consult precisely to solve this since this kind of thing is what I like best and have experience.

Fiat 147 todo detonado andando pelas ruas

Only the error causes the release of the appeal later. The release is so immediate that it can take just over 1 or 2 nanoseconds to initiate the release (in most cases it will take a few ns, but if it starts to take more than this is wrong). To conclude it may take longer, up to us or ms, but this is rare and should always suspect if there is something wrong. And remembering that the . NET need not necessarily wait for completion.

All memory is released when releasing the resource?

No, not at all. The memory of the object containing the resource is never released at the time it releases the resource, they are separate things. The release of the memory of the object container of the resource, which is usually quite small compared to the resource, but this varies somewhat, is only released/destroyed when the GC determines, and this only happens when it can prove that nowhere else in the application it can be accessed more.

The object itself remains alive even if it is not being used, at least until the next GC execution (xiii, the thing is getting worse, because it is not even guaranteed that in every execution of the GC the object is destroyed, becomes more nondeterministic yet, to ensure that a resource is released by the GC may be necessary to call the GC.Collect() several times and we can not even know how many are needed, can be millions in an extreme case, unless already have a complete collection, which is very slow, IE, do this and destroy the performance of your application).

This does not mean anything about the resource that has already been released.

There it was stated that the GC will release the resources because it has already been advised that the object is no longer in use. But the GC (at least the tracing) does not exist precisely to determine whether the object is in use or not and does not need to be warned? This is confusing.

There is no warning of using, the Dispose() or something like GC to release something later or something like.

But there may be a warning yes, but it is precisely to do the opposite, it is a warning not to release the resource, because the Dispose() has already done so.

Remember I told you the GC could finalize the object and release the resource on an emergency basis if the code had failed to do this on time? Well, if everything was done right the GC should not do this, the destructor should not be called, and this is the only warning that the Dispose() does to the GC.

It is not quite that it warns the GC, it marks the object for the GC after knowing that it should not finish.

Obviously this only occurs if the Dispose() is spelled correctly, does not happen magically.

The using actually gives some warning or communicates with the GC to indicate that he must release these resources?

To release the resource not, to warn that it has already been released can be interpreted that has a warning, even if it is not quite this that occurs.

There’s nothing in the Dispose() communicating with the AG?

Yes, the method GC.SuppressFinalize() does this as stated above. See more about him.

Documentation is always right?

No, this is a myth that many believe. But the biggest problem is how people interpret the documentation, and why a lot of people make something work but it’s not right (see the photo above). People believe what they see working, when they should believe what is written in the documentation.

Do you know what you should do with what is not written? Consider that it does not exist. Do you know why? Because it does not exist! If you don’t have a written guarantee in the documentation of something consider that it is not guaranteed, even if you know you can do that.

I’m not even talking about incorrect or incomplete documentation. And that’s a lot, including from Microsoft. This year I had a conversation with a good part of the . NET team, C#, VS, etc. in Redmond at the invitation of Microsoft, in particular with the Jared Parsons and the Immo Landwerth We talked about the documentation flaws that screwed them that take care of C# and . NET.

Photos (since my credibility was questioned): Jared Parsons Immo Landwerth

There we even joked about the use of the famous Thread.Sleep() that people find in examples of documentation and do not know why the application is slow, and are surprised when you take this and it is fast. In conclusion, people don’t even know how to use documentation, they think they have everything they need to know about it and just copy the examples that are there that everything will be fine. Sorry.

The most important thing is that the documentation of a method speaks only the most important thing about it, it doesn’t say all the repercussions it will have, especially if this is implementation detail because that kind of detail can change and exactly why it can’t be documented. But you know how the current implementation works :)

And finally, I must call GC.Collect() manually? When? What happens bad if I call? Why does the method exist if I shouldn’t call it?

You should not call him manually, ever! Or almost, I speak of this in another question. This is never relative, of course for specific tests or debugging may be useful. In case of emergency because you have found a serious problem in memory management, you can put to run for a very short period to minimize a problem even if it causes others, but that allows the use of the application.

If you call manually makes the young objects that die soon and have the collection very inexpensively pass to the next generations prematurely, keeping the object in the most difficult area to collect giving a much worse job to the GC, and in some cases disabling the application, which is what can best happen to you (because then you will have to solve the problem instead of whining that is not good).

Understand more about the generations of . NET GC.

The method exists precisely for diagnosis, for experiencing, or extraordinary salvation, not for putting into production in almost all cases. There’s some kind of structure that it can be useful, but almost no programmer uses it, it’s too complex and who knows how to handle it can handle GC, you probably don’t even know what I’m talking about so rare that you use it.

It’s in the documentation, yes, there is, not in the documentation of the method, but has. It’s on Rico Mariani’s blog (one more page of him talking about it and that he is very clear not to use), one of . NET’s top experts (I recommend your entire blog to anyone who wants to understand about. NET - he was employed at the time involved in the creation and main evolution of . NET and GC is one of the subjects he worked most, it is good to warn here because some people do not read and think it does not matter, yes had who disdained these links as if they were unreliable, for example, from where did the Eric Lippert that is nothing, only the creator of the compiler of C# and the best answers of all Soen, in addition to taking care of Hack on Facebook), and has several responses on Soen, well voted, given by several people, some well reputed in every way (not only points in the OS). And here you have it, too, but since most of it was posted by me and my credibility has been challenged (no argument or any basis to talk about it, other than someone who has some history to indicate that they know the subject) don’t consider my answers so important.

The person you questioned said it doesn’t matter all these links of all these qualified people, what she thinks matters, and I was called arrogant. I can talk nonsense about subjects I don’t understand well, have answers from me that are questionable, not everything I post is 100% right, but this subject I’m proud of what I say, I can say something that someone doesn’t even understand because it’s not an easy subject for most people, but it’s not often that I get it wrong. I may not know anything about this, but it’s hard for me to know wrong. You can say this was pretentious, but it needed to be said, I don’t think I suffer from Dunning-Kruger in this, I even know the limitations I have on the subject.

Call GC.Collect() after the using "to release the resource soon" is the coarse and opposite gambiarra to the purpose, it is wrong!

I preferred not to go into the detail that people who call this method do not call the GC.WaitForPendingFinalizers() which can further aggravate things, because who calls the GC.Collect() is already doing something wrong, rather than causing enough problem, IE, is an advanced feature that depends on much knowledge and pees in the hand of a child. Don’t go near this if you don’t master the GC.

This is necessary because the collection is asynchronous and nothing guarantees that it is finished. So until the statement that this method will release the resource immediately is wrong if you take the idea strictly. I was reluctant to write this because it can create confusion for many people. The feature may take a while, but pro . NET has already been released immediately.

Stop anyone who wants to go deeper has GC documentation and source code from where it shows all this and why calling this method is harmful.

#Completion

The subject is even more complicated than that, the GC has many nuances and the way to create the finishing and layout is very complicated, and almost all programmers should stay away from this. There are some "library creators" out there who do not know how to create this tip ode object and does a lot of damage out there, I’ve seen application suffering and the fault was the library that the person used, there is no using right that it comes in handy.

More about Garbage Collector:

  • As predicted the negatives came without feedback.

  • As fortunately I have not yet lost curiosity tell me in what "everyone uses wrong Httpclient"?

  • You can’t keep creating and killing him like we see in code around, like I did once (not here), only creates one per application, and so it usually doesn’t even get discarded (interestingly has a connection with what we talked about in the other comment because it is a case that you do not usually use the using with him :) ). It has more details, but in comment it is basically this. I remembered this by writing the answer, as I don’t usually use it I had even forgotten what I discovered when I went to see the documentation :D You may not make a mistake, but almost every code I see misses, see the other question there.

  • Being part of . NET’s development team should be an exciting life conclusion.

  • Of course, something can always escape me, but I am aware that I have to ensure that Dispose() is always called before the object, which uses it, is available for GC.

  • @as a general rule, yes, but I do not guarantee that this is mandatory in all cases. Of course, if it can be different, it’s extraordinary, it’s not normal. I am only saying that I have no information not that there is something forcing this that you mentioned, but I can also see scenario (I may be mistaken) that to have the resource but not the object has some utility. Even if you do different you’ll have a risk.

  • Could you explain better how 'using' and 'Disposis' work in dependency injections? Or recommend some reading to try to better understand this part?

  • You’d have to ask a question because it’s a lot to comment on, apart from being another subject, probably showing an example. Wonder if it’s not easy to ask this question right :)

Show 3 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.