位图类没有';t处理流

本文关键字:处理 位图 | 更新日期: 2023-09-27 17:57:42

因此,在发现Bitmap类希望原始流在图像或位图的生命周期内保持打开状态后,我决定查明Bitmap类在处理流时是否真的关闭了流。

查看源代码,Bitmap和Image类创建了一个GPStream实例来包装流,但不存储对GPStream或stream实例的引用

num = SafeNativeMethods.Gdip.GdipLoadImageFromStreamICM(new GPStream(stream), out zero);

现在,GPStream类(内部)没有实现Release或Dispose方法,也没有实现任何允许GDI关闭或处理流的方法。由于Image/Bitmap类没有保留对GPStream实例的引用,因此GDI、Drawing.Bitmap或Drawing.Stream似乎完全没有办法正确关闭流。

我可以用位图的子类来修复这个问题,但是,哦,等等,它是密封的

请告诉我我错了,MS并没有让不可能用API编写不泄露资源的代码。

请记住(a),Bitmap对流没有托管引用,这意味着GC将在流仍在使用时收集它;(b).NET API接受Bitmap/Image引用,并且不确定何时使用它们

位图类没有';t处理流

由于您在本例中提供了流,我想您应该负责处理它。

一个很好的做法是使用打开流和关闭流的方法。这样就更容易跟踪泄漏情况。如果有另一个对象关闭您打开的流,那将是非常奇怪的。

因为位图不能保证析构函数的调用顺序,所以它不会关闭流,因为它可能在垃圾收集过程中已经用自己的析构函数关闭了。Jeffrey Richter的CLR via C#中有一章是关于内存管理的,这一章的解释比我所能解释的要清晰得多。

这个问题的一个简单解决方法是:

var image = new Bitmap(stream);
image.Tag = stream;

现在,流被映像引用,在映像引用之前不会被垃圾收集。如果您的流恰好是MemoryStream,则不需要对其进行处理(它的Dispose是一个no-op)。如果没有,你可以在处理图像时处理它,或者让GC在它接近它时处理它。