DeanR DeanR - 3 months ago 8
ASP.NET (C#) Question

Garbage collection from Main method (infinite loop)

I am implementing an infinite task that runs every so often via a .net console application. However I am concerned that the below will result in a memory leak. Since Main is static (this is where my knowledge on garbage collection gets foggy) does it not mean that the object that I create within the try and catch won't be picked up by the garbage collector until Main finishes (which is never)?

Could someone please explain how the garbage collector would behave in this case?

public static void Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.RollingFile("Logs/log-{Date}.txt")
.CreateLogger();
while (true)
{
try
{
Thread.Sleep(1000);
new UpdatePlayer().Run();
}
catch (Exception ex)
{
Log.Error(ex.ToString());
}
}
}

Answer

You'll have no memory leak: Main doesn't have any reference to UpdatePlayer() instance:

 ...
 try
 {
     Thread.Sleep(1000);

     // Instance created, executed
     new UpdatePlayer().Run();
 }

 // And can be safely collected here when the instance is out of scope (`try {...}`)
 // the anonymous instance can't be accessed and that's enough 

A sample with memory leak:

 // please notice, that anchor is outside the `while(true)` scope  
 List<Object> anchor = new List<Object>(); 
 ...

 while (true)
 {
      try
      {
         Thread.Sleep(1000);

         // Instance created
         var item = new UpdatePlayer();
         // anchored
         anchor.Add(item);
         // and executed
         item.Run();          
      } 

      // item can't be collected here: anchor has a reference to it
      // And the item potentially can be accessed by, say, anchor[0] 

Edit: and if you move the collection into the while(true) scope, the code will be without memory leak:

      try
      {
         List<object> pseudoAnchor = new List<object>(); 

         // Instance created
         var item = new UpdatePlayer();
         // tried to be anchored (illusion)
         pseudoAnchor.Add(item);
         // and executed
         item.Run();          
      } 
      ...

      // the only reference to item is pseudoAnchor, but
      // pseudoAnchor has not been referenced, and so GC
      // can safely collect entire pseudoAnchor with all its items 
      // (just one `item` in fact) 
Comments