主方法的垃圾回收(无限循环)

本文关键字:无限循环 方法 | 更新日期: 2023-09-27 18:03:02

我正在实现一个通过。net控制台应用程序每隔一段时间运行一次的无限任务。然而,我担心下面的操作会导致内存泄漏。由于Main是静态的(这就是我对垃圾收集的了解变得模糊的地方),这是否意味着我在try和catch中创建的对象不会被垃圾收集器拾取,直到Main完成(这是永远不会)?

有人能解释一下垃圾收集器在这种情况下的行为吗?

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());
            }
        }
    }

主方法的垃圾回收(无限循环)

您将没有内存泄漏:Main 任何引用UpdatePlayer()实例:

 ...
 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 

有内存泄漏的示例:

 // 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] 

编辑:如果您将集合移动到while(true)作用域,代码将是而没有内存泄漏:

      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) 

因为Main是静态的(这是我对垃圾收集的知识变得模糊的地方),这是否意味着我在try和catch中创建的对象不会被垃圾收集器拾取,直到Main完成(这是永远不会)?

不,那是假的。

垃圾收集器能够释放任何对象的内存,它可以证明不能再从托管代码访问。在这种情况下,很明显,在Run方法结束后(除非您将对该对象的引用存储在其他地方),该对象将不再可访问,因此允许GC释放它(可能需要一些时间来这样做,但允许)。