从文件中打开图像,然后释放锁定?

Posted

技术标签:

【中文标题】从文件中打开图像,然后释放锁定?【英文标题】:Open Image from file, then release lock? 【发布时间】:2011-09-28 09:55:47 【问题描述】:

我正在使用以下代码行从文件中打开Image

pictureBox1.Image = Image.FromFile("test.png");

我希望它锁定文件,将图像加载到内存,将pictureBox1.Image 设置为内存中的副本,然后释放锁定。实际上,直到我在内存中的Image 中的Dispose() 之前,锁才会消失。在我正在使用的内存中的文件删除之前,我无法释放硬盘上不再使用的文件的锁定。 微软的网站在一篇标有 C# 的文章中提到了它,但是他们的解决方案是用 visual basic 编写的,这对我来说毫无用处。

总结: 我想将pictureBox1.Image设置为存储在"test.png"中的图像,然后让用户编辑或删除"test.png"或其他任何东西。

【问题讨论】:

.Net 的优点是 VB 代码很容易翻译成 C#,反之亦然:developerfusion.com/tools/convert/vb-to-csharp 您的图片是 GIF 吗?此条目中的当前答案不适用于此。请参阅此***.com/a/22017675/354756 【参考方案1】:

使用流的方法不正确

请看这里https://***.com/a/8701748/355264

以上链接的正确代码:

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

    img = new Bitmap(bmpTemp);

【讨论】:

是的,你的应该是接受的答案。将代码粘贴到您的答案中 有关正在发生的事情的详细讨论,请参阅this answer。值得注意的是,.Clone() 方法将保持文件锁定,即使在原始文件为 .Disposed() 之后也是如此。复制构造的克隆,如本答案所示,是这样做的方法。 Better approach 如果要保留原始位图的 PixelFormat。【参考方案2】:

或者更好的是,使用using 语句(下面的代码是从 sylon 的 [已删除] 帖子中复制的)。这样,如果Image.FromStream 抛出异常,您仍然可以确保流立即关闭。

using (FileStream stream = new FileStream("test.png", FileMode.Open, FileAccess.Read))

    pictureBox1.Image = Image.FromStream(stream);

【讨论】:

非常糟糕。你永远不要这样做,它会在以后引起问题。阅读:***.com/a/8701748/355264 路人,不要这样做。最好在打开后复制构造ImageBitmap,然后复制构造用于从文件打开的.Dispose()。这将释放文件锁定。请注意,.Clone() 副本将保持文件锁定,即使在原始文件为 .Disposed() 之后也是如此。复制构造的副本将释放文件锁定。 See here. 如果你这样做,你会得到 GDI+ 错误,如果你尝试 .Clone() 图像也会出现“OutOfMemory”错误。 我喜欢这种方法,因为 .NET 4.6.2/4.7 和 .NET Core 中的 FileStream 有第三个参数,它允许在读取时释放锁以允许多个用户同时读取相同的文件。但是,我使用 ImageMagick 进行转换。【参考方案3】:

您也可以使用流读取图像然后关闭流。

FileStream stream = new FileStream("test.png", FileMode.Open, FileAccess.Read);
pictureBox1.Image = Image.FromStream(stream);
stream.Close();

【讨论】:

【参考方案4】:

我发现的最简单的方法是冻结包含源(文件路径)的对象。所有可以包含图像的控件,似乎都有一个 .Source,如果不为空,它将锁定它指向的文件。

现在的诀窍是将 Image 控件更改为“只读”状态,然后解锁文件。

我的解决方案:

    private Image CreatePreviewImage()
    
        Image ReportImage = new Image();
        Uri path = new Uri(@"C:\Folder\Image1.png");
        if (File.Exists(path.OriginalString))
        
            ReportImage.Name = "Report1";
            ReportImage.Source = LoadImageFromFile(path);
        
        return ReportImage;
    

    public ImageSource LoadImageFromFile(Uri path)
    
        BitmapImage bitmap = new BitmapImage();
        bitmap.BeginInit();
        bitmap.UriSource = path;
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
        bitmap.DecodePixelWidth = 900;
        bitmap.EndInit();
        bitmap.Freeze(); //This is the magic line that releases/unlocks the file.
        return bitmap;
    

【讨论】:

注意:BitmapImage 是一个 WPF 类;最初的问题是关于 WinForms Bitmap。很高兴看到,如果有人使用 WPF,BitmapImage 为这个长期存在的烦恼提供了解决方案。【参考方案5】:

谈论开放、阅读和释放

StreamReader streamReader = new StreamReader("picture.png"); 位图 tmpBitmap = (Bitmap)Bitmap.FromStream(streamReader.BaseStream); streamReader.Close(); 图片框1.Image = tmpBitmap;`

【讨论】:

你所说的“敞开心扉”是什么意思? 我刚刚阅读了主要问题“打开图像文件”,所以我假设第一个操作是定位图像文件以获取路径和文件名。我理解这个问题是否有误? 4行代码由“Open”作为第一行,“Read”作为第二行,“Release”作为第三行组成。以及额外的第 4 行来显示结果。 这似乎是一个很好的答案,我只是不知道你所说的“说话”是什么意思 这似乎类似于五年前的lahsrah's answer。

以上是关于从文件中打开图像,然后释放锁定?的主要内容,如果未能解决你的问题,请参考以下文章

WPF数据绑定到图像文件永远锁定该文件[重复]

站点关闭时防止打开文件锁定

如何使用 Selenium Python 单击锁定图像文件

SQL Server:本地查询时间与网络查询时间...和锁定

Spring Data:如何锁定一个事务中的一行,让其他事务等到它被释放?

设备锁定时在 Today 扩展中加载文件