87548

Why GC does not collect an unused object

Question:

I'm trying to understand how the GC acts when an object is not being used anymore, my test is to do nothing with the object (after used) but it didn't work, the object's destructor was never called.

I've created an example program trying to wait until the object is destroyed, but after 4 hours running nothing happens.

Note: I know if I set the object to null the GC will collect it, but I just want to see the "normal" way the GC itself collects the object.

using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { internal class Program { private const string FilePath = @"C:\objLifeCycle.txt"; private static void Main(string[] args) { var result = GetList(); Console.WriteLine("Results received! Object Id: [{0}] time: [{1}]", result.ObjId, DateTime.Now); //result = null; Task.Factory.StartNew(() => { while (true) { Thread.Sleep(2000); Console.WriteLine("..."); GC.Collect(); } }); Console.ReadKey(); } private static LinkList GetList() { return new LinkList(FilePath) { "link1", "link2", "link3" }; } } } internal class LinkList : List<string> { internal string ObjId { get; set; } internal string FilePath { get; set; } internal LinkList(string filePath) { ObjId = Guid.NewGuid().ToString(); FilePath = filePath; WriteFile($"Object LinkList with Id [{ObjId}] has been created at [{DateTime.Now}]"); } ~LinkList() { WriteFile($"Object LinkList with Id [{ObjId}] has been destroyed at [{DateTime.Now}]"); Environment.Exit(0); } private void WriteFile(string line) { var sw = new StreamWriter(FilePath, true); sw.WriteLine(line); sw.Close(); } }

Answer1:

GC will not collect free resources in a deterministic Way. The program should need memory to ask for resources. If there are enough resources the GC won't collect anything because there is not necessary. Also the GC could collect memory only in program "Idle" states...

I strongly recommend you to read: <a href="http://www.telerik.com/blogs/understanding-net-garbage-collection" rel="nofollow">Understanding .NET Garbage Collection</a>

As you can test and see in documentation there is no way to force a garbage collection even calling <a href="https://msdn.microsoft.com/en-us/library/xe0c2357%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396" rel="nofollow">GC.Collect()</a>

<img alt="GC.Collect documentation" class="b-lazy" data-src="https://i.stack.imgur.com/3JKHy.png" data-original="https://i.stack.imgur.com/3JKHy.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" />

And besides of that actually you need to understand that there are some GC flavors depending on platform and CLR implementations

<a href="https://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/" rel="nofollow">Cross-VM Object Collections</a>

For test purposes you can increase the need of Collect memory using <a href="https://msdn.microsoft.com/en-us/library/xe0c2357%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396" rel="nofollow">GC.AddMemoryPressure Method (Int64)</a>

Answer2:

The GC <em>will</em> collect the object, but only in Release mode.

In Debug mode, the variable result will exist as long as it's in scope, even if you don't use it, so that the debugger can keep showing you its value. But this also means the object can't be garbage collected.

In Release mode, .Net is smart enough to realize the object will not be used anymore, so it will be eligible for garbage collection. And when the GC is invoked (in your case explicitly by calling GC.Collect()), it will collect it.

Recommend

  • Is it possible to expose Dropwizard metrics in logs
  • Django - Get unused/all options in a select tag
  • How to create a Promise for nested async calls
  • How to get to type parameters of a reflect.runtime.universe.Type in scala? [duplicate]
  • C# where to add a method
  • Find the associated program to open a file using Java
  • C++ slows over time reading 70,000 files
  • The symbol you provided is not a function
  • VB.NET 2012 Property Set on Property Get
  • Retrieve IP address of device
  • Conversion from string “a” to type 'Boolean' is not valid
  • Code in Job's Script Block after Start-Process Does not Execute
  • Display java JPanel in a JFrame
  • Is playing sound in Javascript performance heavy?
  • How to Cache Real-time Data?
  • Make VS2015 use angular-cli ng at build time in a .NET project
  • Spring Data JPA custom method causing PropertyReferenceException
  • Insert into database using onclick function
  • Possible to stop flickering java tooltip in heavyweight mode?
  • output of program is not same as passed argument
  • Knitr HTML Loop - Some HTML output, some R output
  • Can a Chrome extension content script make an jQuery AJAX request for an html file that is itself a
  • Upload files with Ajax and Jquery
  • Akka Routing: Reply's send to router ends up as dead letters
  • How to pass list parameters for each object using Spring MVC?
  • Numpy divide by zero. Why?
  • AT Commands to Send SMS not working in Windows 8.1
  • php design question - will a Helper help here?
  • How to delete a row from a dynamic generate table using jquery?
  • Windows forms listbox.selecteditem displaying “System.Data.DataRowView” instead of actual value
  • AngularJs get employee from factory
  • Proper way to use connect-multiparty with express.js?
  • using HTMLImports.whenReady not working in chrome
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • Authorize attributes not working in MVC 4
  • apache spark aggregate function using min value
  • unknown Exception android
  • EntityFramework adding new object to nested object collection
  • Checking variable from a different class in C#
  • Sorting a 2D array using the second column C++