何时处置asp.net控件

本文关键字:控件 net asp 何时处 | 更新日期: 2023-09-27 18:11:22

我正在寻找一个asp.net网站的内存泄漏。我发现的一个问题是,当不再需要控件时,代码没有释放事件处理程序。我使用MSDN上显示的处理模式来清理它们,并将调用用于删除if (disposing)块内的事件处理程序,因为它们是托管资源,但是除非我将析构函数添加到每个页面并让它们都手动处理控件,否则在结束器清理混乱之前不会触发任何操作。这样做将是脆弱的,并且使将来重新引入泄漏相对容易;忽略终止器运行的代码中不接触非托管对象的约定会不会更好?

// Design pattern for a base class.
public class Base: IDisposable
{
   //Implement IDisposable.
   public void Dispose() 
   {
     Dispose(true);
      GC.SuppressFinalize(this); 
   }
   protected virtual void Dispose(bool disposing) 
   {
      if (disposing) 
      {
         myControl.SomeEvent -= SomeEventHandler;
         // Free other state (managed objects).
      }
      // Free your own state (unmanaged objects).
      // Set large fields to null.
   }
   // Use C# destructor syntax for finalization code.
   ~Base()
   {
      // Simply call Dispose(false).
      Dispose (false);
   }
}

何时处置asp.net控件

何时处置asp.net控件

永远不要,如果有活引用的话。

如果您有任何Disposable对象,则调用Dispose方法是最佳实践。如果您只是允许它们离开作用域,它们将在第一个垃圾收集周期中被添加到终结队列中。并将在结束后的第二个垃圾收集周期中释放内存。如果您可以调用Dispose方法和SuppressFinalization,那么最终化是不必要的开销。

另一件事是在你的代码示例中。有Finalize方法,但没有任何非托管代码。如果您查看Finalize->Dispose(false)的执行路径,您会注意到它什么都不做。因为只有当disposing。因此,如果没有任何非托管对象,则没有必要添加Finalize方法。

对象将被添加到finalize Queue中,并且只有当该对象没有任何活动引用(在第一个GC周期中)时才调用Finalize方法。所以,取消注册必要事件是你的责任。否则,只要存在对该对象的引用,Finalize就永远不会执行。

关于取消注册事件处理程序,这里有一个很好的参考。

有必要显式删除c#中的事件处理程序吗

你唯一需要触摸它的时间是当你想要清理它现在

或者如果你要进入一个创建了很多对象的块。

否则——让GC决定。

注。为什么不使用USING机制呢?

只有当垃圾收集器决定它准备好运行时,才会清理对象。通常,只有在需要清理非托管资源(如文件句柄等)或外部连接时才会实现dispose。如果你在很长一段时间内通过多个集合看到这些资源,那么很可能有什么东西在某处保留了一个引用。

从我看来,dispose的使用并没有错……它不会给你带来任何东西。您正在删除对事件的引用,但是底层对象将保留在堆上,直到GC决定收集它们。