【问题标题】:Image.FromStream does not hold a ref to the underlying streamImage.FromStream 不持有对底层流的引用
【发布时间】:2023-03-11 18:55:01
【问题描述】:

我有一些代码可以做

MemoryStream ms = new MemoryStream();
...
return Image.FromStream(ms);

它以非常折衷的方式失败,因为 Image 对象不持有流的引用,因此如果 GC 启动导致 GDI+ 错误,它可以被释放。

我该如何解决这个问题(无需将流保存到磁盘,或更改我的方法信号)?

【问题讨论】:

    标签: c# .net image


    【解决方案1】:

    这对我来说似乎不太可能 - 几乎任何使用 Image.FromStream 都会导致问题。

    在我看来更有可能是某些东西正在处理您的 MemoryStream,这是不应该的。

    您能否提供一个简短但完整的程序来演示该问题?强制垃圾收集应该使其相对容易重现 - 你甚至可以创建自己的类,从 MemoryStream 派生,并使用终结器来显示它是否真的被收集(嗯,至少完成了) .

    【讨论】:

    • @Sam: 如果流中有更多数据,read 应该总是大于 0 - 但它很容易小于 buffer.Length,即使有更多之后数据仍在流中。
    • 是的,原来是这样的:stackoverflow.com/questions/2340337/…
    【解决方案2】:

    如果不稍微更改代码,就没有办法做到这一点。 Remarks section for the documentation for the static FromStream method on the Image class states

    您必须保持流打开 图片的生命周期。

    话虽如此,您必须确保在图像访问流时,流是打开的。看起来(通过反射器查看)FromImage 方法实际上并没有导致 Image 实例保留对从中加载图像的 Stream 的引用。

    话虽这么说,您可以以某种方式将图像和 MemoryStream(或 Stream)链接在一起,这样它就不会被 GCed。如果不真正保留图像的“所有权”(它被传递),那么我建议您创建一个数据结构来保存对 Image 和 Stream 的引用,并将两者一起传递。

    【讨论】:

    • 我不明白。如果图像需要打开流,那么它必须持有对它的引用,对吧?
    • @Issac Cambron:是的,这很好,但它指的是 Stream 处于打开状态,而不是引用有效。为此,如果您正在传递图像并且无法控制它何时关闭(或者当图像仍然需要它时,您可能在其他地方自己关闭它)。我正在更新答案以反映这一点。
    • @Sam Saffron:如果您克隆图像,我认为您仍然必须保留流。 Clone 方法的文档并不太明确,说它产生了一个“精确副本”,可以用多种不同的方式解释。如果克隆也需要打开原始流,我不会这样做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 2011-05-26
    • 2013-05-16
    • 1970-01-01
    • 1970-01-01
    • 2015-01-15
    • 1970-01-01
    相关资源
    最近更新 更多