为什么Image.FromFile有时会保持文件句柄打开?

Sim*_*ver 20 gdi+ filehandle

我在ASP.NET应用程序中使用.NET中的GDI +进行了大量的图像处理.

我经常发现Image.FromFile()保持文件句柄打开.

为什么是这样?在没有保留文件句柄的情况下打开图像的最佳方法是什么.

  • 注意:我没有做任何愚蠢的事情,就像保持Image对象一样 - 即使我是,我也不希望文件句柄保持活动状态

jam*_*con 35

我在这个帖子上和其他一些海报一样经历了同样的旅程.我注意到的事情:

  1. 在释放文件句柄时,使用Image.FromFile似乎无法预测.在所有情况下调用Image.Dispose()都没有释放文件句柄.

  2. 使用FileStream和Image.FromStream方法可以工作,如果在FileStream上调用Dispose(),或者按照Kris的建议将整个事件包装在Using {}语句中,则释放文件上的句柄.但是,如果您尝试将Image对象保存到流中,则Image.Save方法将引发异常"GDI +中出现一般错误".据推测,Save方法中的某些东西想知道原始文件.

  3. 史蒂文的方法对我有用.我能够使用内存中的Image对象删除原始文件.我还能够将图像保存到流和文件中(我需要做这两件事).我还能够保存到一个与原始文件同名的文件,如果你使用Image.FromFile方法记录的那些文件是不可能的(我发现这很奇怪,因为这肯定是最有可能的用例,但是嘿.)

总而言之,打开你的Image就像这样:

Image img = Image.FromStream(new MemoryStream(File.ReadAllBytes(path)));
Run Code Online (Sandbox Code Playgroud)

然后,您可以根据需要随意操作它(以及原始文件).


Ste*_*ven 14

我遇到了同样的问题,并使用了阅读文件

return Image.FromStream(new MemoryStream(File.ReadAllBytes(fileName)));

  • 不知道为什么我的答案被否决了.它将在不保持手柄打开的情况下读取. (2认同)

Kri*_*son 5

Image.FromFile保持文件句柄处于打开状态,直到图像被释放.来自MSDN:

"文件保持锁定状态,直到图像被丢弃."

使用Image.FromStream,您将不会遇到问题.

using(var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
    return Image.FromStream(fs);
}
Run Code Online (Sandbox Code Playgroud)

编辑:(一年又一点)

上面的代码是危险的,因为它是不可预测的,在某个时间点(关闭文件流之后)你可能会得到可怕的"GDI +中发生一般错误".我会修改为:

Image tmpImage;
Bitmap returnImage;

using(var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
    tmpImage = Image.FromStream(fs);
    returnImage = new Bitmap(tmpImage);
    tmpImage.Dispose();
}

return returnImage;
Run Code Online (Sandbox Code Playgroud)