我有这段代码:
using (var img = Bitmap.FromFile(path))
{
result = new Bitmap(img);
}
问题:
- 实例是否
Bitmap
在使用结束时立即调用?还是在等待垃圾收集? - 它是从当前线程还是从其他线程处理的?
我有这段代码:
using (var img = Bitmap.FromFile(path))
{
result = new Bitmap(img);
}
问题:
Bitmap
在使用结束时立即调用?还是在等待垃圾收集?您实际上有两个Bitmap 实例 -img
和result
.
img
将在块的末尾被处理(我相信在当前线程上)using
。编译器会为您在块中 插入一个Dispose
调用。finally
result
不会自动处理 - 任何消耗结果都需要处理它。
另请注意,处理和垃圾收集是两件不同的事情 -Dispose
将立即清理任何非托管资源(在位图的情况下,它将是底层图形对象),但任何托管资源将在稍后的时间被垃圾收集,未确定的时间.
您的代码等效于以下代码(实际上是编译器翻译代码的方式):
try
{
var img = Bitmap.FromFile(path);
result = new Bitmap(img);
}
finally
{
img.Dispose();
}
请注意,result
从未Dispose
调用过它,并且由调用代码正确处理对象。
它既不是垃圾收集也不是处置。您编写这样的代码来创建位图的深层副本。与Bitmap.Clone()
创建浅拷贝不同。您使用它来避免锁定路径文件。稍后当您尝试将图像保存回来时,此类锁定可能会非常麻烦,这会失败并出现 GenericException。
Bitmap(Image) 构造函数使用 Graphics.DrawImage() 创建副本。img 变量上的using语句释放文件上的锁定。
顺便说一句,这并非完全没有问题,深拷贝会消耗大量内存,并且当图像很大时会显着增加进程的提交大小。或者换句话说,它很昂贵,并且您将面临程序因 OutOfMemoryException 被炸毁的风险。还有一个缺陷,Bitmap(Image) 构造函数忘记复制 Image.HorizontalResolution 和 VerticalResolution 属性。所以图像可能不会以相同的大小显示。
using
是try/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 总是在当前线程中调用。