Dispose() - 什么叫这个和什么时候

时间:2013-09-06 16:05:32

标签: c# .net dispose idisposable

我有这段代码:

using (var img = Bitmap.FromFile(path))
{
    result = new Bitmap(img);
}

问题:

  1. 在使用结束时是否立即调用Bitmap实例?还是等待垃圾收集?
  2. 是从当前线程还是其他线程处置?

4 个答案:

答案 0 :(得分:3)

您实际上有两个位图实例 - imgresult

img将在using块的末尾处理(我相信当前的线程)。编译器会在Dispose块中为您插入finally调用。

result不会自动处理 - 无论消费结果都需要处理它。

另请注意,处理和垃圾收集是两回事 - Dispose将立即清除所有非托管资源(在Bitmap的情况下,它将是底层图形对象)但是,任何托管的资源都将被垃圾收集,因为它们会在稍后的未确定时间内被收集。

答案 1 :(得分:2)

您的代码等同于以下(实际上编译器如何翻译代码):

try
{
    var img = Bitmap.FromFile(path);
    result = new Bitmap(img);
}
finally
{
    img.Dispose();
}

请注意result从未调用Dispose,并且由调用代码来正确处理对象。

答案 2 :(得分:1)

既不是垃圾收集也不是处置。您编写这样的代码来创建位图的深层复制。与创建浅拷贝的Bitmap.Clone()不同。您可以使用它来避免锁定路径文件。稍后当您尝试将图像保存回来时,此类锁定可能非常麻烦,因为GenericException失败。

Bitmap(Image)构造函数使用Graphics.DrawImage()创建副本。 img变量上的 using 语句释放对文件的锁定。

这并非完全没有麻烦btw,深度复制会花费大量内存,并且可能会在图像很大时显着增加进程的提交大小。或者换句话说,它很昂贵,你将冒着使用OutOfMemoryException进行程序轰炸的风险。还有一个缺陷,Bitmap(Image)构造函数忘记复制Image.Horizo​​ntalResolution和VerticalResolution属性。因此图像可能无法以相同的尺寸显示。

答案 3 :(得分:0)

usingtry/finally模式的语法糖,在括号关闭后,Img.Dispose();将在后面调用。

using (var img = Bitmap.FromFile(path))
{
   result = new Bitmap(img);
}  // here Dispose will be immediately called.

if you are using img/result here you will get an Exception.

线程与此事无关! Dispose始终在当前线程中调用。