2010-10-02 25 views
12

是否可以使用System.Drawing.Image的FromStream方法,而不必在图像的整个生命周期内保持该流的打开状态?从流中加载图像而不使流保持打开状态

我有一个应用程序,它使用Image.FromStreamAssembly.GetManifestResourceStream的组合加载一堆来自资源文件的工具栏图形。

我遇到的问题是,虽然这可以在Windows 7上正常工作,但在Windows XP上,如果禁用链接到这些图像之一的用户界面元素,则应用程序会崩溃。在Windows 7上,图像以灰度呈现。在XP上,它会因内存不足异常而崩溃。

经过加载的头发后,我终于追溯到图像的初始加载。作为理所当然的事,如果我创建实施IDisposable,它也破坏了相同方法的对象,我把它包在using语句,例如

using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName)) 
{ 
    image = Image.FromStream(resourceStream); 
} 

如果我删除using语句,这样该流ISN不会处理,那么应用程序不会在XP上崩溃。但是我现在有一堆悬挂的“孤儿”流 - 图像存储在命令类中,这些图像在处理它们时正确处理图像,但原始流不是。

我检查了FromStream的文档,它确认流需要保持打开状态。但是,为什么在Windows 7开发系统上没有崩溃和烧毁,这是一个谜!

我真的不希望这个流挂起来,我当然不希望存储对这个流以及图像的引用,所以我可以稍后处理它。我只需要一次这样的流,所以我想摆脱它:)

是否有可能创建图像,然后杀死那里的流?

+3

通过在'System.Drawing'中的'OutOfMemoryException'通常意味着* GDI +中的一般错误*。这是因为[历史](http://stackoverflow.com/questions/2610416/is-there-a-reason-image-fromfile-throws-an-outofmemoryexception-for-an-invalid-im)到非管理错误代码的映射。 – 2010-10-02 11:35:49

+0

如果您传递给Image.FromStream的流不可查找,则可以安全地关闭流。但这是无证的行为,所以请自担风险。 – user2452157 2016-06-17 07:41:28

回答

19

原因流需要开放是following

GDI +,因此System.Drawing中命名空间,可能直到位由图像所需延迟的原始图像的比特的解码。另外,即使在图像解码之后,GDI +也可以确定丢弃大量位图的内存并稍后重新解码会更高效。因此,GDI +必须能够访问图像的源位,才能访问位图或对象。

文件记载的解决方法是创建使用Graphics.DrawImage或创建从原始图像的索引Bitmap任一非索引图像如下所述:

Bitmap and Image constructor dependencies

+0

感谢您的非常有用的答案!我知道FromFile锁定文件,但我从来不知道为什么直到现在。我已经使用创建非索引图像方法进行了测试,该方法运行良好,并且应用程序不再在我的XP虚拟机上崩溃。我将再次使用索引方法进行测试,看看会发生什么 - 我不清楚这两种类型之间的差异。 – 2010-10-02 12:08:39

+2

Fwiw:他们修复了Vista版gdiplus.dll中索引像素格式的几个问题。他们很高兴这么做,但是当你的代码需要在XP上运行时会很头痛。一般来说,请远离他们以避免这种麻烦。 – 2010-10-02 12:45:05

0

您可以将流保存到临时文件并使用Image.FromFile方法。或者根本不要嵌入图像,将其保存为文件并在运行时从该文件加载。

+0

感谢您的回答,尽管这是我已经丢弃的东西,正如我从过去的经验中知道的那样,因此锁定文件将无法在应用程序结束之前将其删除。 – 2010-10-02 12:09:48

2

根据Image.FromStream的文档,流在打印图像时必须保持打开状态。因此,即使关闭工作(并且没有什么可说的,在丢弃它之前无法关闭它,只要流对象本身就行),这可能不是一个非常可靠的方法。

您可以将图像复制到另一个图像对象,然后使用它。但是,这可能会比保持数据流畅通更有记忆力。

+0

感谢您的回答。这就是我所使用的,使用上面链接的知识库文章,其中提供了原因。 – 2010-10-02 12:10:28

+0

它也做了详细说明,但在某些情况下保持流可能更有效率,值得记住。 – 2010-10-02 12:26:39