【问题标题】:Releasing managed objects in static clasess在静态类中释放托管对象
【发布时间】:2016-08-02 08:48:13
【问题描述】:

在静态/共享类中释放托管对象的最佳做法是什么?

我持有 3 个大型数据表,大部分时间不使用它们。

GC 不会释放它们,因为它们是静态的 - 对吗?

我想知道在 ReleaseDatatables() 中将它们设置为 null 是否有用,还是我只是在浪费时间?

谢谢。

public static class Helpers 
{
    private static DataTable _branchDT;
    public static DataTable branchDT
    {
       get
       {
           if (_branchDT == null)
           {
               _branchDT = new DataTable();
               _branchDT = Orange.ProjectManagment.DAL.Database.getDataset("SELECT * FROM Branches").Tables[0];
               return _branchDT;
           }
           else
           {
               return _branchDT;
           }
       }
       set { _branchDT = value; }
   }

   private static DataTable _departmentDT;

   public static DataTable departmentDT
   {
       get 
       {
           if (_departmentDT == null)
           {
               _departmentDT = new DataTable();
               _departmentDT = Orange.ProjectManagment.DAL.Database.getDataset("SELECT * FROM Departments").Tables[0];
               return _departmentDT;
           }
           else
           {
               return _departmentDT;
           }
       }
       set { _departmentDT = value; }
   }

   private static DataTable _TeamsDT;

   public static DataTable TeamsDT
        {
            get
            {

                if (_TeamsDT == null)
                {
                    _TeamsDT = new DataTable();
                    _TeamsDT = Orange.ProjectManagment.DAL.Database.getDataset("SELECT * FROM Teams").Tables[0];
                    return _TeamsDT;
                }

                else
                {

                    return _TeamsDT;
                }

            }

            set { _TeamsDT = value; }
        }


       /// <summary>
       /// setting all datatables to null in order to free memory or to make them refresh them self in the next call to get property method
       ///
       /// </summary>
       public static void ReleaseDatatables()
        {
                // datatables set to null, hence next call to them they will refresh via new query to db in get prop method
                branchDT = null;
                departmentDT = null;
                TeamsDT = null;
        }

【问题讨论】:

  • “我持有 3 个大型数据表,大部分时间都不使用它们”那你为什么要存储它们呢? 当你向数据库询问数据时需要它,不要将旧数据保存在内存中。
  • 我认为这是一个选项,但仍然想知道将它们设置为 null 是否有用
  • 在创建成本高且保留成本低的情况下缓存数据是明智的。 DataTable 的区别在于它的创建成本很高,而且维护起来通常也很昂贵。根据行数,一个永远不会减少的数字。然而,像团队、分支机构和部门这样的数据项应该有一个合理的上限。唯一的另一个问题是,当 dbase 表更改时,您的数据可能很容易变得陈旧。做决定是程序员的工作,我们不能替你做。
  • 根据 MS 的说法,当“操作足够昂贵,您想与用户沟通,他们应该考虑缓存结果。”时使用一种方法。详情:msdn.microsoft.com/en-us/library/…

标签: c# .net vb.net memory-management


【解决方案1】:

GC 在计算是否可以释放内存的信息时检查“根”。如果任何引用类型变量绑定到根,则不会收集对象。

您的静态对象是这些根中的一个,因此如果您将变量设置为 null,那么您的大数据将不会被绑定到根并会被释放。

另外,您可以查看WeakReference object types here 这是您的情况的另一种方法


更新

但您的解决方案对我来说似乎不是最佳实践。从 db 表中读取所有数据是非常危险的,因为您不知道那里存储了多少数据。最好使您的属性 IEnumerable 并在没有此缓存的情况下对数据块使用“yield return”。当然,这取决于您要执行的操作的上下文。

【讨论】:

  • 谢谢你,我会支持你在更新部分写的做法。
【解决方案2】:

是的。但是静态类不需要发布。

静态类不需要释放,因为它们不是对象,也不消耗内存。

静态类中的静态字段是消耗内存的对象。它们不会被释放,因为它们在应用程序关闭之前是可以访问的。 如果您想释放一些内存,请将该字段设置为 null。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    相关资源
    最近更新 更多