由新位图(filePath)locking的免费文件

我有一个图片框指向一个特定的文件“A”的图像,在执行时间,我想改变图片框的图像到不同的“B”,但我得到以下错误:

mscorlib.dll中出现第一个偶发的“System.IO.IOException”types的exception。附加信息:进程无法访问文件“A”,因为它正在被另一个进程使用。

我设置图像如下:

pbAvatar.Image = new Bitmap(filePath); 

我如何解锁第一个文件?

提前致谢!

一旦文件被读取和处理,使用文件stream将解锁文件:

 using (var fs = new System.IO.FileStream("c:\\path to file.bmp", System.IO.FileMode.Open)) { var bmp = new Bitmap(fs); pct.Image = (Bitmap) bmp.Clone(); } 

编辑:更新以允许处理原始位图,并允许FileStream被closures。

这个答案 不安全 – 请参阅注释,并参阅net_prog的答案 。 编辑使用Clone不会使它更安全克隆所有领域,包括文件stream引用,在某些情况下会导致问题。

这是我的方法来打开图像,而不locking文件…

 public static Image FromFile(string path) { var bytes = File.ReadAllBytes(path); var ms = new MemoryStream(bytes); var img = Image.FromStream(ms); return img; } 

更新:我做了一些性能testing,看哪种方法是最快的。 我比较它@net_progs“复制从位图”答案(这似乎是最接近正确的,但确实有一些问题)。 我为每种方法加载图像10000次,并计算每个图像的平均时间。 结果如下:

 Loading from bytes: ~0.26 ms per image. Copying from bitmap: ~0.50 ms per image. 

结果似乎有意义,因为您必须使用位图方法的副本两次创build图像。

这是在网上广泛讨论的一个常见的locking问题。

与streambuild议的技巧将无法正常工作 ,实际上它起初工作,但稍后会导致问题。 例如,它将加载图像,文件将保持解锁状态,但如果尝试通过Save()方法保存加载的图像,则会引发通用的GDI +exception。

接下来,每像素复制的方式似乎并不坚实,至less它是嘈杂的。

我发现工作是在这里描述: http : //www.eggheadcafe.com/microsoft/Csharp/35017279/imagefromfile-locks-file.aspx

这是应该如何加载图像:

 Image img; using (var bmpTemp = new Bitmap("image_file_path")) { img = new Bitmap(bmpTemp); } 

我正在寻找解决这个问题的方法,到目前为止,这个方法对我来说工作的很好,所以我决定去描述它,因为我发现很多人在这里和networking上都提出错误的stream方法。

在位图对象仍在使用时,您不能处理/closuresstream。 (位图对象是否需要再次访问它只是确定性的,如果你知道你正在使用什么types的文件,以及你正在执行什么操作 – 例如对于某些.gif格式的图像,构造函数返回。)

克隆创build位图的“精确拷贝”(每个文档; ILSpy显示调用本地方法,因此现在追踪太多)可能会复制该stream数据 – 否则它不会是确切的副本。

最好的办法是创build一个像素完美的图像副本 – 尽pipeYMMV(某些types的图像可能有多个帧,或者也可能需要复制调色板数据)。但对于大多数图像来说, :

 static Bitmap LoadImage(Stream stream) { Bitmap retval = null; using (Bitmap b = new Bitmap(stream)) { retval = new Bitmap(b.Width, b.Height, b.PixelFormat); using (Graphics g = Graphics.FromImage(retval)) { g.DrawImage(b, Point.Empty); g.Flush(); } } return retval; } 

然后你可以像这样调用它:

 using (Stream s = ...) { Bitmap x = LoadImage(s); } 

这是我目前使用的技术,似乎最好的工作。 它具有生成与源文件具有相同像素格式(24位或32位)和分辨率(72 dpi,96 dpi,无论)的位图对象的优点。

  // ImageConverter object used to convert JPEG byte arrays into Image objects. This is static // and only gets instantiated once. private static readonly ImageConverter _imageConverter = new ImageConverter(); 

这可以根据需要经常使用,如下所示:

  Bitmap newBitmap = (Bitmap)_imageConverter.ConvertFrom(File.ReadAllBytes(fileName)); 

编辑:这是上述技术的更新: https : //stackoverflow.com/a/16576471/253938

( 接受的答案是错误的,当你试图在克隆的位图上的LockBits(...)最终会遇到GDI +错误。)


我看到只有3种方法摆脱这个问题:

  • 复制你的文件到一个临时文件,并打开简单的方法new Bitmap(temp_filename)
  • 打开你的文件,读取图像,创build一个像素大小像素格式副本(不Clone() )和处置第一个位图
  • (接受locking文件function)

将它读入stream中,创build位图,closuresstream。

三年前,我写了一个图片浏览器程序,看看我能不能做到。 过去一周我添加了扫描图像的代码。 (我计划在出现​​错误后将其添加到族谱程序中。)要裁剪未使用的区域,我要让程序调用带有文件名称的MSPaint。 我在那里编辑然后保存。 当我closures画图时,图像显示更改。
如果我对图像做了任何事情,我正在获取有关该文件被locking的错误。 我使用Image,FromStream()更改程序来locking图像。 我不再在Paint中得到这个消息。 (我的程序在VB 2010中)