- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我从阅读中知道the Microsoft documentation IDisposable
的“主要”用途接口(interface)是清理非托管资源。
对我来说,“非托管”意味着诸如数据库连接、套接字、窗口句柄等。但是,我已经看到了 Dispose()
的代码。方法用于释放托管资源,这对我来说似乎是多余的,因为垃圾收集器应该为您处理这些。
例如:
public class MyCollection : IDisposable
{
private List<String> _theList = new List<String>();
private Dictionary<String, Point> _theDict = new Dictionary<String, Point>();
// Die, clear it up! (free unmanaged resources)
public void Dispose()
{
_theList.clear();
_theDict.clear();
_theList = null;
_theDict = null;
}
MyCollection
使用的垃圾收集器释放内存?比平时快吗?
_theList
在上面的代码中包含一百万个字符串,您想立即释放该内存,而不是等待垃圾收集器。上面的代码能做到吗?
最佳答案
Dispose要点是 释放非托管资源。它需要在某个时候完成,否则它们将永远不会被清理。垃圾收集器不知道 怎么样致电 DeleteHandle()
在 IntPtr
类型的变量上,它不知道是否是否需要拨打DeleteHandle()
.
Note: What is an unmanaged resource? If you found it in the Microsoft .NET Framework: it's managed. If you went poking around MSDN yourself, it's unmanaged. Anything you've used P/Invoke calls to get outside of the nice comfy world of everything available to you in the .NET Framework is unmanaged – and you're now responsible for cleaning it up.
public void Cleanup()
要么
public void Shutdown()
但是,此方法有一个标准化名称:
public void Dispose()
甚至创建了一个界面,
IDisposable
,只有一种方法:
public interface IDisposable
{
void Dispose()
}
所以你让你的对象暴露
IDisposable
接口(interface),这样你就保证你已经编写了一个方法来清理你的非托管资源:
public void Dispose()
{
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
}
你已经完成了。
除了你可以做得更好。
Dispose()
(意味着他们不再计划使用该对象)为什么不摆脱那些浪费的位图和数据库连接?
Dispose()
摆脱这些托管对象的方法:
public void Dispose()
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//Free managed resources too
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose();
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose();
this.frameBufferImage = null;
}
}
一切都很好,
除了你可以做得更好 !
Dispose()
在你的对象上?然后他们会泄漏一些
非托管 资源!
Note: They won't leak managed resources, because eventually the garbage collector is going to run, on a background thread, and free the memory associated with any unused objects. This will include your object, and any managed objects you use (e.g. the
Bitmap
and theDbConnection
).
Dispose()
,我们仍然可以保存他们的培根!我们仍然有办法为他们调用它:当垃圾收集器最终开始释放(即完成)我们的对象时。
Note: The garbage collector will eventually free all managed objects.When it does, it calls the
Finalize
method on the object. The GC doesn't know, orcare, about your Dispose method.That was just a name we chose fora method we call when we want to getrid of unmanaged stuff.
Finalize()
来做到这一点。方法。
Note: In C#, you don't explicitly override the
Finalize()
method.You write a method that looks like a C++ destructor, and thecompiler takes that to be your implementation of theFinalize()
method:
~MyObject()
{
//we're being finalized (i.e. destroyed), call Dispose in case the user forgot to
Dispose(); //<--Warning: subtle bug! Keep reading!
}
但是该代码中有一个错误。你看,垃圾收集器在
上运行后台线程 ;您不知道销毁两个对象的顺序。完全有可能在您的
Dispose()
代码,
托管 您试图摆脱的对象(因为您想提供帮助)不再存在:
public void Dispose()
{
//Free unmanaged resources
Win32.DestroyHandle(this.gdiCursorBitmapStreamFileHandle);
//Free managed resources too
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose(); //<-- crash, GC already destroyed it
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose(); //<-- crash, GC already destroyed it
this.frameBufferImage = null;
}
}
所以你需要的是
Finalize()
的方法告诉
Dispose()
应该
不碰任何托管 资源(因为它们可能不再存在),同时仍然释放非托管资源。
Finalize()
和
Dispose()
双方都致电
第三个 (!) 方法;如果您从
Dispose()
调用它,则传递一个 bool 值说明(与
Finalize()
相反),这意味着释放托管资源是安全的。
Dispose(Boolean)
:
protected void Dispose(Boolean disposing)
但更有用的参数名称可能是:
protected void Dispose(Boolean itIsSafeToAlsoFreeManagedObjects)
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//Free managed resources too, but only if I'm being called from Dispose
//(If I'm being called from Finalize then the objects might not exist
//anymore
if (itIsSafeToAlsoFreeManagedObjects)
{
if (this.databaseConnection != null)
{
this.databaseConnection.Dispose();
this.databaseConnection = null;
}
if (this.frameBufferImage != null)
{
this.frameBufferImage.Dispose();
this.frameBufferImage = null;
}
}
}
然后你改变了
IDisposable.Dispose()
的实现方法:
public void Dispose()
{
Dispose(true); //I am calling you from Dispose, it's safe
}
和你的终结者:
~MyObject()
{
Dispose(false); //I am *not* calling you from Dispose, it's *not* safe
}
Note: If your object descends from an object that implements
Dispose
, then don't forget to call their base Dispose method when you override Dispose:
public override void Dispose()
{
try
{
Dispose(true); //true: safe to free managed resources
}
finally
{
base.Dispose();
}
}
一切都很好,
除了你可以做得更好 !
Dispose()
在您的对象上,那么一切都已清理干净。稍后,当垃圾收集器出现并调用 Finalize 时,它将调用
Dispose
再次。
Dispose()
,您将再次尝试处理它们!
Dispose
。在垃圾对象引用上。但这并没有阻止一个微妙的错误潜入。
Dispose()
时: handle
CursorFileBitmapIconServiceHandle 被摧毁。稍后当垃圾收集器运行时,它会再次尝试销毁同一个句柄。
protected void Dispose(Boolean iAmBeingCalledFromDisposeAndNotFinalize)
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle); //<--double destroy
...
}
解决这个问题的方法是告诉垃圾收集器它不需要费心完成对象——它的资源已经被清理干净,不需要更多的工作。您可以通过拨打
GC.SuppressFinalize()
来做到这一点。在
Dispose()
方法:
public void Dispose()
{
Dispose(true); //I am calling you from Dispose, it's safe
GC.SuppressFinalize(this); //Hey, GC: don't bother calling finalize later
}
现在用户已经拨打了
Dispose()
, 我们有:
Object.Finalize
的文档说:
The Finalize method is used to perform cleanup operations on unmanaged resources held by the current object before the object is destroyed.
IDisposable.Dispose
:
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
It's your choice! But choose
Dispose
.
~MyObject()
{
//Free unmanaged resources
Win32.DestroyHandle(this.CursorFileBitmapIconServiceHandle);
//A C# destructor automatically calls the destructor of its base class.
}
问题是你不知道垃圾收集器什么时候会完成你的对象。您未管理、不需要、未使用的 native 资源将一直存在,直到垃圾收集器最终运行。然后它会调用你的终结器方法;清理非托管资源。
的文档Object.Finalize 指出这一点:
The exact time when the finalizer executes is undefined. To ensure deterministic release of resources for instances of your class, implement a Close method or provide a
IDisposable.Dispose
implementation.
Dispose
的优点清理非托管资源;您可以了解和控制何时清理非托管资源。它们的破坏是“确定性的”。
It is therefore very difficult indeed to write a correct finalizer,and the best advice I can give you is to not try.
关于c# - 正确使用 IDisposable 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/538060/
据我所知,这是一个公认的规则,如果你有一个具有 IDisposable 成员 m 的类 A,A 应该实现 IDisposable 并且它应该在其中调用 m.Dispose()。 我找不到令人满意的理由
我有一个父类和子类都需要实现IDisposable。 virtual(和 base.Dispose()?)调用应该在哪里发挥作用?当我只是重写 Dispose(bool disposing) 调用时,
我意识到这个问题正在寻找的查询不足以找到 IDisposable 实现的每一个小问题,但每个早期警告都很重要,所以我会尽我所能。 我想知道是否有人提出了 NDepend 的 CQL 查询,该查询将列出
我对 C# 还是比较陌生,只是在过去几天才接触到“IDisposables”。我可以掌握 using block 的概念来处理必须处理的对象,而无需手动记住调用 .Dispose() 方法 - 方便!
在我的应用程序中,我有一个每隔几秒创建一次的大对象。我用它做了一些工作,然后就不再需要它了。 我在任务管理器中看到,即使我没有对该对象的任何引用并且需要收集它,ram 大小也会增加。 在实现 IDis
考虑一下: interface IFoo : IDisposable { } class Program { static void Main() { var foo = GetFoo
我是这么认为的。但是请看一下 ASP.NET 中的内置类: public sealed class HttpPostedFile { public Stream InputStream { g
昨天,在我们的代码库上运行 Visual Studio 代码分析后,以下代码被突出显示为一个问题: using (var stringReader = new StringReader(someStr
我认为这个问题说明了一切。 谢谢。 最佳答案 如果对象拥有该资源,他们应该实现IDisposable。通常不需要将事物设置为 null,尽管它没有坏处。 如果您不拥有该资源,那么显然您不应该处置它,并
MSDN 文档和 StackOverflow 上的许多答案竭尽全力讨论如何正确实现 IDisposable,例如MSDN IDisposable , MSDN Implementing IDispos
如果一个类继承自一个本身实现了 IDisposable 的接口(interface),该类是否也应该实现 IDisposable? 例如 internal IMyInterface : IDispos
当 出现时,正确处理接口(interface)的默认实现的最佳方法是什么?接口(interface)不继承自 IDisposable ?例如,假设我想做 public class FooGetter
我有一个实现 IDisposable 的类,因为它有一个 IDisposable 的私有(private)成员字段“foo”(在构造函数中初始化)。我意外地收到了 CA2000 代码分析错误,它希望我
如果我有一个相当标准的抽象类,它允许注入(inject)一个 IDisposable 实例。但是,一些继承自此类的类不应处置注入(inject)的存储库,而其他类则应处置。显而易见的解决方案是有一个构
这个问题在这里已经有了答案: Declare IDisposable for the class or interface? (7 个答案) 关闭 4 年前。 我想问的是,如果类 A 继承自 Int
我有一个“永远”存在于应用程序中的 IDiposable 对象。在我的例子中是 SemaphoreSlim,但这个问题实际上适用于任何可以处置的对象。 我确信只要应用程序运行,我就需要一个对象。所以问
我有一堆 IDisposable查找表中的对象(现在是普通的旧字典<>),但为了简化代码并避免错误,我正在寻找一个“拥有”它所拥有的项目的集合类,并避免重新发明轮子 - 这样做一个类已经存在? 规范应
很久以前来自 C/C++ 的我仍然有确保所有资源都被正确清理的习惯。我总是确保在 IDisposable 类上调用 Dispose 并在包含一次性对象的类中实现 Dispose 模式。 但是,在我的环
如果我有实现 IDisposable 的接口(interface)(来自 apress 书中的示例)像这样 public interface IArchitectRepository : IDispo
问题是如何测试调用 Finalize 时对象释放资源的事实。类的代码: public class TestClass : IDisposable { public bool HasBeenDi
我是一名优秀的程序员,十分优秀!