c# - .NET PictureBox - 如何确保资源已释放

标签 c# dispose picturebox

我在用户控件中有一个OpenFileDialogPictureBox。为了更好地理解这个问题,我将用几句话解释这个用户控件的工作原理。用户可以选择要为表单打开的图像。该图像的名称保存在数据库中,并且该图像的文件被复制到默认位置。当数据库中保存了一些图像时,当加载带有图片框控件的表单时,该图像就会加载到图片框中。如果用户选择另一个图像并想要使用新图像保存表单,我有一种方法可以小心地从我的默认位置删除旧图像文件,这就是问题发生的地方。

当我加载图像并尝试保存新图像时,有时(实际上非​​常罕见)我会收到一条错误消息,资源正在被另一个进程使用..我可以粘贴确切的错误如果需要的话。我认为问题是由图片框及其处理图像的方式引起的。

这是我的代码:

if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    if (MyImage != null)
                    {
                        MyImage.Dispose();

                    }
                    selectedFile = openFileDialog1.FileName;
                    selectedFileName = openFileDialog1.SafeFileName;

                    MyImage = new Bitmap(openFileDialog1.FileName);
                    pictureBox1.Image = (Image)MyImage;

                    int imageWidth = pictureBox1.Image.Width;
                    int picBoxWidth = pictureBox1.Width;

                    if (imageWidth != 0 && picBoxWidth > imageWidth)
                    {
                        pictureBox1.Width = imageWidth;
                    }
                    else
                    {
                        pictureBox1.Width = defaultPicBoxWidth;
                    }
                }
                catch (Exception ex)
                {
                    logger.Error(ex.ToString());
                    MessageBox.Show("Error loading image!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

以及我的删除方法:

public void DeleteImage(AppConfig imageInfo, string imageName)
        {
            string imgPath = imageInfo.ConfigValue.ToString();
            try
            {
                File.Delete(imgPath + "\\" + imageName);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

我认为:

if (MyImage != null)
                        {
                            MyImage.Dispose();

                        }

会处理这个问题,但有时仍然会发生。而且因为并非每次都如此,所以处理它就更加重要,因为在某些时候我可能会决定我已经解决了它,但事实上只是在一段时间内很幸运。

最佳答案

    MyImage = new Bitmap(openFileDialog1.FileName);
    pictureBox1.Image = (Image)MyImage;

是的,该代码会锁定文件。该锁是由 GDI+ 创建的内存映射文件对象生成的,该对象可以有效地将文件的像素数据映射到内存中,而无需在分页文件中分配空间。只要图像显示在图片框中并且未被处理,您就无法删除该文件,锁定可以防止这种情况。您必须先处理该图像并将 Image 属性设置回 null,然后才能删除该文件。

您可以通过在内存中复制图像来防止文件被锁定:

    using (var temp = new Bitmap(openFileDialog1.FileName)) {
        pictureBox1.Image = new Bitmap(temp);
    }

当然,如果图像很大,就应该避免这样做。并且请注意,另一个进程实际上可能对该文件有类似的锁定。你对此无能为力。

关于c# - .NET PictureBox - 如何确保资源已释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15274463/

相关文章:

c# - DbCommand 和连接 - 为什么 dispose 不关闭底层连接?

reporting-services - 处理时的 SSRS ReportViewer nullreference 异常

c# - NUnit 2016 抛出.TypeOf

c# - 在代码隐藏中访问外部样式表

flutter - 在 dispose 方法中访问 BlocProvider.of<Bloc>(context)

c# - 在当前鼠标位置缩放/拉伸(stretch)图片框?

c# - 为什么我不应该使用 PictureBox 控件?

c# - 将 PictureBox 中的图片移动到另一个 PictureBox

c# - 在 C# 中使用 Monad 的引人注目的场景是什么

c# - 单元测试垃圾收集