由新位图(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中)