【问题标题】: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"或其他任何东西。

【问题讨论】:

标签: c# winforms image locking


【解决方案1】:

使用流的方法不正确

请看这里https://stackoverflow.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);
}

【讨论】:

  • 非常糟糕。你永远不要这样做,它会在以后引起问题。阅读:stackoverflow.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
    猜你喜欢
    • 1970-01-01
    • 2017-10-04
    • 2021-11-20
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-08
    相关资源
    最近更新 更多