asp.net 控件何时被处置
我正在寻找 ASP.NET 网站中的内存泄漏问题。我发现的一个问题是,当不再需要控件时,代码不会释放事件处理程序。我按照 MSDN 上所示的处置模式来清理它们,并将调用以删除 if (处置) 块内的事件处理程序,因为它们是托管资源,但除非我通过并向每个页面添加析构函数,并让它们全部手动处理控件,直到终结器清理混乱为止,不会触发任何操作。这样做会很脆弱,并且使将来重新引入泄漏变得相对容易;我最好忽略关于不接触终结器运行的代码中的非托管对象的约定吗?
// 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);
}
}
I'm hunting memory leaks in an asp.net website. One that I found was that the code wasn't releasing event handlers when controls were no longer needed. I went with the disposing pattern as shown on MSDN to clean them up, and put the calls to remove the event handlers inside the if (disposing)
block since they were managed resources, but unless I go through and add destructors to each page and have them all manually dispose the controls nothing fires until the finalizer cleans up the mess. Doing it that way would be brittle and make re-introducing a leak in the future relatively easy; would I be better off ignoring the convention about not touching non-managed objects in code ran by the finalizer?
// 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);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
从不(如果有任何实时引用)。
如果您有任何
Disposable
对象,则调用Dispose
方法是最佳实践。如果您只是允许它们超出范围,它们将在第一个垃圾收集周期中添加到终结队列中。并会在终结后的第二个垃圾回收周期中释放内存。如果您可以调用Dispose
方法和SuppressFinalization
,则终结会产生不必要的开销。另一件事在你的代码示例中。拥有 Finalize 方法,而无需任何非托管代码。如果您查看 Finalize->Dispose(false) 的执行路径,您会发现它什么也没做。因为所有的托管对象只有在
dispose
时才会被处理。因此,如果您没有任何非托管对象,则添加 Finalize 方法是没有意义的。仅当该对象没有任何实时引用(在第一个 GC 周期中)时,该对象才会被添加到 Finalization Queue 并调用 Finalize 方法。因此,您有责任取消注册必要的事件。否则,只要存在对该对象的引用,
Finalize
就永远不会执行。这是关于取消注册事件处理程序的一个很好的参考。
是否有必要在 C# 中显式删除事件处理程序
Never, if there is any live reference.
Calling the
Dispose
method is best practice if you have anyDisposable
Objects. If you just allow them to go out of scope, they will be added to the finalization queue in the first garbage collection cycle. And will release the memory in the second garbage collection cycle after finalization. Finalization is an unwanted overhead if you can call theDispose
method andSuppressFinalization
.And the other thing is in your code example. Having a
Finalize
method without having any unmanaged code. If you look at the execution path of the Finalize->Dispose(false) you can notice that it does nothing. Because all the managed objects are handled only ifdisposing
. So, there is no point of addingFinalize
method if you don't have any unmanaged objects.The object will be added to the Finalization Queue and call the
Finalize
method only if that object doesn't have any live references (in the first GC cylcle). So, it's your duty to un-register necessary events. OtherwiseFinalize
will never execute as long as there is a reference to that object.Here is a good reference for you on un-registering event handlers.
Is it necessary to explicitly remove event handlers in C#
您唯一需要触摸它的时候是当您现在想要清理它时
,或者您要进入一个会产生大量物体的方块时。
否则 - 让 GC 决定。
ps为什么不使用USING机制?
the only time you need to touch it is when you want it to be cleaned NOW
Or if you are going to enter a block which creates a lot of objects.
Otherwise - let the GC decide.
p.s. why don't you use the USING mechanism ?
只有当垃圾收集器决定它准备好运行时,您的对象才会被清理。一般来说,只有当您需要清理非托管资源(如文件句柄等)或外部连接时,您才会实施处置。如果您长时间并通过多个集合查看这些资源,那么某些内容可能在某处保留了引用。
从我看来,使用 dispose 并没有错……它并没有真正给你带来任何东西。您将删除对事件的引用,但底层对象将保留在堆上,直到 GC 决定收集它们。
Your objects would only be cleaned up once the garbage collector decides that it is ready to run. Generally, you would only implement a dispose if you needed to clean up non-managed resources (like filehandles etc) or external connections. If you are seeing these resources for a long time and through multiple collections then something is probably holding on to a reference somewhere.
The use of dispose is not wrong from what I see ... its not really getting you anything. You are dropping the reference to the event but the underlying objects are going to remain on the heap until the GC decides to collect them.