ChatGPT解决这个技术问题 Extra ChatGPT

How to force garbage collector to run?

c#

Interviewer asked me about this today ...is there an answer ?

This question has good info about why you shouldn't do that though: stackoverflow.com/questions/118633/…
why are you telling like this
@Jason - Maybe the interviewer didn't want to hear the solution, rather get Andrew's knowledge and reasoning against doing it, then this question could effectively make sense.
@martinstoeckli It is still a terrible question. Someone with the knowledge in a stressful interview would not realise it is a trick question, or think to supply additional info. Then the question doesn't help the interviewer distinguish between someone with the knowledge or someone without it. So the question is still terrible.
"When do you force garbage collection?" sounds like a good interview question to me ("How": not so much). Beginner: I dunno. Intermediate: Never. Expert: When you write a test for memory leaks.

P
Pang

System.GC.Collect() forces garbage collector to run. This is not recommended but can be used if situations arise.


Why is it not recommended?
GC.Collect() is expensive to run. Doing it more than necessary is inadvisable. The code for when it should be called is well written. You should normally only self collect in specialized edge cases. stackoverflow.com/a/21961777/2710988
C
CMedina

It is not recommended to call gc explicitly, but if you call

GC.Collect();
GC.WaitForPendingFinalizers();

It will call GC explicitly throughout your code, don't forget to call GC.WaitForPendingFinalizers(); after GC.Collect().


WaitForPendingFinalizers doesn't necessarily give "better performance": it simply blocks until all objects in the finalisation queue have been finalised (objects which might have been put there by your previous call to Collect). If you want a chance for those objects to be collected then you need another call to Collect after calling WaitForPendingFinalizers.
Since one of the few good reasons to call gc.Collect is as a last-ditch effort to free up resources that weren't properly disposed, WaitForPendingFinalizers would seem a necessary step. Not sure what the best practice would be to avoid calling gc.Collect excessively in such cases, though. BTW, I wonder if there's any technical reason that gc.Collect 'has' to promote generations? It would seem more useful to have generations stay put unless enough stuff has been allocated in one to justify advancing it.
Note for beginners in C# (like me): GC force call doesn't guarantee, some concrete unused object be removed from memory. (one way to do this is using of "using statement" (msdn.microsoft.com/ru-ru/library/yh598w02(v=vs.80).aspx))
Why is it supposed to be important to call WaitForPendingFinalizers?
S
Srinivas Reddy Thatiparthy
GC.Collect() 

from MDSN,

Use this method to try to reclaim all memory that is inaccessible. All objects, regardless of how long they have been in memory, are considered for collection; however, objects that are referenced in managed code are not collected. Use this method to force the system to try to reclaim the maximum amount of available memory.


m
J
Justin Niessner

GC.Collect();

Keep in mind, though, that the Garbage Collector might not always clean up what you expect...


What do you mean by that? What could it unexpectedly clean?
@Voldemort - It wouldn't unexpectedly clean anything. But it may not clean up everything that you expect it to.
t
thecoop

You do not want to force the garbage collector to run.

However, if you ever did (as a purely academic exercise, of course):

GC.Collect()

I prefer @Karthik's answer, there can be situations where an app should legitimately call GC.Collect(). Very rarely though.
Say you had an array of weak references and wanted to check if any 'live' references existed. It would make sense to call GC.Collect() before checking. Just saying.
Downvoted because the opening statement is factually incorrect; Yes, I do want to force the garbage collector to run.
y
yagohaw

I think that .Net Framework does this automatically but just in case. First, make sure to select what you want to erase, and then call the garbage collector:

randomClass object1 = new randomClass
...
...
// Give a null value to the code you want to delete
object1 = null;
// Then call the garbage collector to erase what you gave the null value
GC.Collect();

I think that's it.. Hope I help someone.


D
David

Since I'm too low reputation to comment, I will post this as an answer since it saved me after hours of struggeling and it may help somebody else:

As most people state GC.Collect(); is NOT recommended to do this normally, except in edge cases. As an example of this running garbage collection was exactly the solution to my scenario.

My program runs a long running operation on a file in a thread and afterwards deletes the file from the main thread. However: when the file operation throws an exception .NET does NOT release the filelock until the garbage is actually collected, EVEN when the long running task is encapsulated in a using statement. Therefore the program has to force garbage collection before attempting to delete the file.

In code:

        var returnvalue = 0;
        using (var t = Task.Run(() => TheTask(args, returnvalue)))
        {
            //TheTask() opens a file and then throws an exception. The exception itself is handled within the task so it does return a result (the errorcode)
            returnvalue = t.Result;
        }
        //Even though at this point the Thread is closed the file is not released untill garbage is collected
        System.GC.Collect();
        DeleteLockedFile();

W
Waruna Manjula

Here is an alternate suggestion. Leave server GC enabled as you have done. Then based on a user defined setting force GC to run if app memory goes above a certain threshold that you determine as the critical level.

Mind you if you follow this path you are effectively stating that you have better knowledge of when garbage collection should run that the CLR does. Most often than not I've found that the CLR does a better job on its own than when we interfere with it.

Code to check memory usage and run GC across either all generations or a specified generation

    long UsedMemory;
//UsedMemory = GC.GetTotalMemory(false); // Not as reliable
UsedMemory = System.Diagnostics.Process.GetCurrentProcess().PagedMemorySize64;
if (UsedMemory > 1073741824) // One GB in bytes 1 X 1024 X 1024 X 1024
{
    GC.Collect(); // Collect all generations
    //GC.Collect(2,GCCollectionMode.Forced);; Or collect a specific generation and force it to run now
}