我从阅读MSDN文档中了解到,IDisposable接口的"主要"用途是清理非托管资源.
对我来说,"非托管"意味着数据库连接,套接字,窗口句柄等等.但是,我已经看到了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;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,这是否使得垃圾收集器可以使用的内存MyCollection比通常更快?
编辑:到目前为止,人们已经发布了一些使用IDisposable清理非托管资源(例如数据库连接和位图)的好例子.但是假设_theList在上面的代码中包含了一百万个字符串,并且你想现在释放那个内存,而不是等待垃圾收集器.上面的代码会实现吗?
我何时在类上实现IDispose而不是析构函数?我读过这篇文章,但我仍然忽略了这一点.
我的假设是,如果我在一个对象上实现IDispose,我可以显式"破坏"它,而不是等待垃圾收集器这样做.它是否正确?
这是否意味着我应该总是在对象上显式调用Dispose?这有什么常见的例子?
如果我理解正确,.net运行时将始终在我之后清理.因此,如果我创建新对象并停止在我的代码中引用它们,运行时将清理这些对象并释放它们占用的内存.
既然这就是为什么一些对象需要有一个析构函数或dispose方法呢?当它们不再被引用时,运行时不会清理它们吗?
我的问题的背景是:我正在转换一个消息处理应用程序,它使用从VB6到C#的许多COM组件.应用程序中的许多COM组件都是细粒度组件,在消息处理循环中使用的数量和频率都很高.与VB6应用程序相比,在C#应用程序中处理一组测试消息时,我看到内存使用量大幅增加(且逐渐增长).我在应用程序上使用了一个内存分析器,它确认了高内存使用量是由应用程序的非托管堆上的COM对象的实时实例引起的.我知道这些组件由于实时引用而没有被"泄露",因为如果我将GC.Collect()放在消息处理循环的核心,那么内存使用率是平坦的,几乎与VB6应用程序相同(尽管性能像人们期望的那样可怕地降级.
我已经阅读了我在C#中的多代垃圾收集器,运行时可调用包装器,非托管资源内存分配,Marshal.ReleaseComObject(),Marshal.FinalReleaseComObject()等中可以找到的所有内容.它们都没有解释为什么应用程序要保留当相应的RCW符合垃圾回收条件时,在非托管堆中实时COM对象.
在一些文章中,我看到了C#中垃圾收集器的实际实现可能涉及优化的可能性,例如不执行特定代中所有符合条件的对象的收集.如果这个或类似的东西是真的,它可以解释为什么没有收集和销毁符合条件的RCW及其相应的COM对象.另一种解释可能是,非托管堆中的COM对象的销毁不直接与其相应RCW的集合相关联.我没有找到任何提供有关如何在.NET中处理COM对象的详细程度的内容.我需要更好地理解这一点,因为我的应用程序的内存使用量目前是不可接受的.任何指针或建议将不胜感激.
编辑:我应该补充一点,我非常熟悉终结器(RCW上没有记录)和IDisposable接口(RCW没有实现).据我所知,Marshal.ReleaseComObject()是显式"处理"COM引用的正确方法.我小心地在我的应用程序中为每个已知的COM对象用法添加该语句,这导致内存使用没有差别.
此外,当添加显式GC.Collect()导致没有内存问题时,不清楚为什么缺少处理或终止代码可能是问题.Dispose()和终结器的存在都不会导致实际的对象集合.前者允许对象抑制其最终化步骤(如果有的话),后者允许清除未在RCW中暴露的非托管资源.
我有一个类产生另一个UI线程,并做它的事情.我需要中止该线程并在我的父类被销毁时进行清理.那么我怎么知道我的父班什么时候被毁坏了呢?
来自C++,我首先想到的是将它放在析构函数中.但是C#并没有任何析构函数 - 只有终结器和处理器 - 根据我的理解 - 可能会也可能不会被调用(我猜这对于GC来说是情绪化的事情).
这非常简单 - 如果您可能想要或不想释放您的资源.
但是,只要对象被销毁,你在哪里放置绝对必须执行的代码?
我尝试在类的析构函数中关闭连接,以确保如果我忘记关闭它 - 它会自动关闭,并引发异常。
我搜索了一下,发现这是不可能的。
现在我尝试关闭它两次 - 并且它有效!
但我想知道这是否是一个好的解决方案。你怎么认为?
这是代码
public class MyCommand : IDisposable
{
public readonly DbCommand command;
public MyCommand(string ConnectionString, DbProviderFactory factory)
{
var tempConnexion = factory.CreateConnection();
tempConnexion.ConnectionString = ConnectionString;
tempConnexion.Open();
var t = tempConnexion.BeginTransaction(IsolationLevel.ReadCommitted);
command = tempConnexion.CreateCommand();
command.Connection = tempConnexion;
command.Transaction = t;
}
public MyCommand(string ConnectionString, DbProviderFactory factory, string requete)
: this(ConnectionString, factory)
{
command.CommandText = requete;
}
public MyCommand(string ConnectionString, string provider)
: this(ConnectionString, DbProviderFactories.GetFactory(provider)) { }
public MyCommand(string ConnectionString, string provider, string …Run Code Online (Sandbox Code Playgroud)