【问题标题】:Cleaning up Resources (Garbage Collection, Using, IDisposable, etc)清理资源(垃圾收集、使用、IDisposable 等)
【发布时间】:2011-12-02 01:19:49
【问题描述】:

我正在尝试弄清楚如何控制垃圾收集器何时收集我的自定义对象 - 我发现了很多使用 IDisposable/Destructors 来执行此操作的参考,但每个示例都有以下内容:

class Car
{
    ~Car()  // destructor
    {
        // cleanup statements...
    }
}

(http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx)

“清理声明”中的实际内容是什么?

我希望能够在我的程序因对象实例而关闭时调用 CarInstance.Dispose() 并让 GC 清理该特定实例 - 这样我就不会在 GC 时出现性能问题自动运行并清理一堆 -

告诉我! 威廉

【问题讨论】:

标签: c# garbage-collection idisposable


【解决方案1】:

只有在需要清理 .Net 无法自动清理的非托管资源时,才应创建终结器。

如果您需要清理昂贵的托管或非托管资源,您应该实施IDisposable。昂贵并不意味着记忆; “昂贵”的托管资源是指对非托管资源(例如,文件、流、GDI+ 等)的封装

无法强制 GC 收集特定对象。

【讨论】:

    【解决方案2】:

    这取决于您所说的“清理” -

    如果您只是指释放托管内存,那么没有直接的方法可以为您的对象清理内存,只有您的对象。事实上,你不会想要这样做——GC 是高效的,并且试图“控制”它往往会弄乱它的启发式。这就是为什么直接调用GC.Collect 是个坏主意的部分原因。

    如果您正在管理资源,例如原生资源,或其他必须发布的类似概念,那么IDisposable 是您的最佳选择。但是,您应该正确实现它,这与您的示例代码非常不同。有关正确实现的详细信息,您可以查看我的series on IDisposable

    【讨论】:

      【解决方案3】:

      您不应该尝试“控制 GC”,除非在极少数情况下。几乎可以保证你不会遇到这种情况。永远。

      IDisposable.Dispose() 与 GC 或析构函数并不真正(直接)相关。

      • Dispose() 用于清理托管资源,内存除外。它需要由您的代码显式调用。作为备份,一些类将调用放在析构函数中。但应该在此之前调用它。
      • 析构函数用于清理非托管资源,通常还包括内存以外的资源。但您也应该在 Dispose() 中这样做。
      • GC 会自动运行并很好地完成工作 - 它会清理对象使用的内存。您通常不应该对此大惊小怪。

      【讨论】:

        【解决方案4】:

        要调用CarInstance.Dispose(),它必须实现IDisposable,然后终结器应该调用Dispose(false),以便所有清理代码都在一个位置。

        遵循此 question 中引用的 Finalize / Dispose 模式。

        至于“清理语句”中应该包含什么内容,这应该包含清理任何非托管资源的代码。 .NET 无法自行清理的东西。

        【讨论】:

          【解决方案5】:

          这是我用于存储库的基类的代码 sn-p。它利用 IDisposable 接口来清理 Linq-to-SQL 上下文。

              /// <summary>
          /// Base class for common functionality shared across Sql repositories.
          /// </summary>
          internal abstract class BaseSqlRepository : IDisposable
          {
              #region Members
              /// <summary>
              /// Linq to Sql data context
              /// </summary>
              private SqlRepositoryDataContext context;
          
              /// <summary>
              /// Determines whether the class has invoked the dispose/finalize functionality.
              /// </summary>
              private bool isDisposed;
              #endregion
          
              #region Constructors
              /// <summary>
              /// Initializes a new instance of the <see cref="BaseSqlRepository"/> class.
              /// </summary>
              protected BaseSqlRepository()
              {
                  this.context = new SqlRepositoryDataContext(InitializeConnectionString());
                  this.isDisposed = false;
              }
          
              protected BaseSqlRepository(SqlRepositoryDataContext Context)
              {
                  this.context = Context;
                  this.isDisposed = false;
              }
          
              /// <summary>
              /// Finalizes an instance of the BaseSqlRepository class.
              /// Releases unmanaged resources and performs other cleanup operations before the
              /// <see cref="BaseSqlRepository"/> is reclaimed by garbage collection.
              /// </summary>
              ~BaseSqlRepository()
              {
                  this.Dispose(false);
              }
          
              #endregion
          
              #region Properties
              /// <summary>
              /// Gets or sets the context.
              /// </summary>
              /// <value>The context.</value>
              protected SqlRepositoryDataContext Context
              {
                  get { return this.context; }
                  set { this.context = value; }
              }
              #endregion
          
              #region Methods
              /// <summary>
              /// Initializes the connection string.
              /// </summary>
              /// <returns>Connection string.</returns>
              protected static string InitializeConnectionString()
              {
                  string connectionName = ConfigurationManager.AppSettings["AppConnection"];
                  string connection = string.Empty;
          
                  if (!string.IsNullOrWhiteSpace(connectionName))
                  {
                      connection = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
                      if (string.IsNullOrWhiteSpace(connection))
                      {
                          throw new ArgumentException("Unable to initialize a connection to the database.");
                      }
                  }
                  else
                  {
                      throw new ArgumentException("Unable to initialize a connection to the database.");
                  }
          
                  return connection;
              }
          
              /// <summary>
              /// Releases unmanaged and - optionally - managed resources
              /// </summary>
              /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
              protected void Dispose(bool disposing)
              {
                  if (!this.isDisposed && disposing)
                  {
                      // Dispose the managed resources of the class
                      this.context.Dispose();
                  }
          
                  // Dipose the un-managed resources of the class
                  this.isDisposed = true;
              }
          
              /// <summary>
              /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
              /// </summary>
              public void Dispose()
              {
                  this.Dispose(true);
                  GC.SuppressFinalize(this);
              }
              #endregion
          }
          

          【讨论】:

            【解决方案6】:

            如果您想控制何时释放特定对象,请为其实现 IDisposable 并显式调用 obj.Dispose()

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2010-10-04
              • 2011-12-11
              • 2015-04-10
              • 2020-05-08
              • 1970-01-01
              • 1970-01-01
              • 2011-03-10
              • 1970-01-01
              相关资源
              最近更新 更多