【问题标题】:Returning image created by Image.FromStream(Stream stream) Method返回 Image.FromStream(Stream stream) 方法创建的图像
【发布时间】:2014-09-30 23:15:34
【问题描述】:

我有这个函数,它在函数中返回一个图像,该图像是使用 Image.FromStream 方法创建的 根据MSDN

您必须在图像的生命周期内保持流打开

所以我没有关闭流(如果我关闭了流,则从返回的图像对象中抛出 GDI+ 异常)。我的问题是,当 Image.Dispose() 在返回的图像上的其他地方调用时,流是否会关闭/处理

public static Image GetImage(byte[] buffer, int offset, int count)
{
    var memoryStream = new MemoryStream(buffer, offset, count);
    return Image.FromStream(memoryStream);
}

正如其中一个答案所建议的那样,使用不是可行的方法,因为它会引发异常:

public static Image GetImage(byte[] buffer, int offset, int count)
{
    using(var memoryStream = new MemoryStream(buffer, offset, count))
    {
         return Image.FromStream(memoryStream);
    }
}

public static void Main()
{
   var image = GetImage(args);
   image.Save(path); <-- Throws exception
}
  1. 根据某些人明确处理/关闭 MemoryStream 是没有必要的,因为它不使用任何非托管资源,其他人则说相反的话,所以这是一种两难境地.
  2. Image.Dispose 方法不会释放创建 Image 的流
  3. Image 类不包含对传递给 Image.FromStream 方法的 Stream 的任何引用,因此该流最终将被 GC 收集...?因此 Image.Save 方法中的异常
  4. 返回一个包装类,其中包含对流的引用和由它创建的图像,从而使我们能够dispose它们...?或者干脆使用 Tag 属性来保持对父流的引用...?
  5. 这个问题似乎只在使用 MemoryStream 时发生。如果图像是从 ConnectStream 创建的,即使父流被释放,也不会发生 bad

【问题讨论】:

标签: c# image stream dispose


【解决方案1】:

尽管其他人建议您这样做,但在处置图像之前,您不应关闭或处置流。

MSDN 状态:

您必须在图像的生命周期内保持流打开。

对于某些流,例如MemoryStream,disposing 没有太多用处,因为它不分配非托管资源。另一方面,文件流会这样做,因此除非您非常确定流是安全的,否则您应该始终在处理完图像后释放流。

【讨论】:

    【解决方案2】:

    由于您只是构建一个 Image 然后保存它,因此请考虑使用此实现:

      public static void GetAndSaveImage(byte[] buffer, int offset, int count,string path)
      {
          using(var memoryStream = new MemoryStream(buffer, offset, count))
          using(var img = Image.FromStream(memoryStream))
          {
              img.Save(path);
          }
      }
    

    【讨论】:

    • 我并没有真正看到这个的用途......你只是打开一个图像来保存它不受影响。
    【解决方案3】:

    处置图像不会影响内存流,如下例所示:

    static void Main(string[] args) {
    
            byte[] contents = File.ReadAllBytes(DESKTOP_PATH + "asample.tif");
            MemoryStream ms = new MemoryStream(contents);
            Image img = Image.FromStream(ms);
            img.Dispose();
            Image img2 = Image.FromStream(ms);
            Console.WriteLine(img2.PixelFormat);
            Console.ReadKey();
    
    
        }
    

    这将输出“Format32bppPargb”。我建议将它包装成这样的 using 语句:

    using (MemoryStream ms = new MemoryStream(contents){
                // code here
            }
    

    【讨论】:

    • 如果我在使用 Image.Save 之间返回图像会抛出异常
    • @AbdullahSaleem 请提供具体的用法示例,以便澄清事情。
    • 您的问题是调用 Image.Dispose() 是否会处理流...所以这就是答案。
    • 不能再同意了,但问题是幕后实际发生了什么。我想处置那个开放的流吗?如果是……怎么办?
    • 一种有效的方法是使用字节数组作为图像,并且只在需要的地方构建一个图像,然后处理流、图像和其他可以处理的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多