【问题标题】:Disposing of image when using PictureBox使用 PictureBox 时处理图像
【发布时间】:2016-11-07 20:57:52
【问题描述】:

我正在使用不久前编写的 Winforms 程序。我遇到了一些问题,我正在尝试优化它处理某些事情的方式,但我遇到了一些处理问题。

以下是目前正在实施的内容。

首先,首先浏览图片文件夹中的文件并将它们复制到预览文件夹中。

foreach (string s in files)
{
    fileName = System.IO.Path.GetFileName(s);
    destFile = System.IO.Path.Combine(path, fileName);
    File.Copy(s, destFile, true);
}

接下来,它通过 ShowDialog 打开一个表单:

frmPreview frm = new frmPreview(FileNameArray, lblParcel.Text);
frm.ShowDialog();

接下来,它会进入预览表单并获取以下代码:

try {
    FlowLayoutPanel imagePanel = new FlowLayoutPanel();
    if (System.IO.Directory.Exists(path))
    {
        folder = new DirectoryInfo(path);

        foreach (FileInfo files in folder.GetFiles())
        {
            System.Diagnostics.Debug.Print(files.Extension);
            if ((string.Equals(files.Extension, ".jpg", StringComparison.OrdinalIgnoreCase)) || (string.Equals(files.Extension, ".gif", StringComparison.OrdinalIgnoreCase)) || (string.Equals(files.Extension, ".png", StringComparison.OrdinalIgnoreCase)))
            {
                PictureBox image = new PictureBox();
                image.Image = Image.FromFile(files.FullName);
                image.SizeMode = PictureBoxSizeMode.Zoom;
                image.Size = this.Size;
                imagePanel.Controls.Add(image);
            }
        }
    }
    this.Controls.Add(imagePanel);
    System.Threading.Thread.Sleep(0);

    return;
}
catch
{
}

上面的代码基本上是把所有的照片都拍下来,每一张都创建一个PictureBox,然后把PictureBox添加到FlowLayoutPanel中显示在一个窗口中进行预览。问题在于它没有正确处理并在第三次尝试访问此预览窗口后被捕获(关闭窗口并再次打开它可以正常工作,但会创建第二个进程)。

最后,它在表单关闭时实现以下内容。

private void frmPreview_FormClosed(object sender, FormClosedEventArgs e)
{
    this.Dispose();
    this.Close();
}

该错误发生在第 3 次调用预览窗口时,即程序通过顶部发布的 foreach 语句。

它捕获的完整行是:

File.Copy(s, destFile, true);

该进程无法访问文件“C:\Users\username\Pictures\Preview\image.jpg”,因为它正被另一个进程使用。

我 99.9% 确定这是因为 PictureBoxFlowLayoutPanel 但我不知道该怎么做才能修复它。我想尽可能少地改变,因为这不是我的程序,它很快就会被完全重写。我主要只需要暂时解决这个问题,直到我们完成整个程序将被废弃的大局。

我发现了一些似乎是类似问题的帖子,但没有一个修复程序根本没有改变任何东西。以下是我查看并尝试实施失败的所有帖子:

file-copy-the-process-cannot-access-the-file

file-is-being-used-by-another-process

dispose-of-a-picturebox

【问题讨论】:

  • 使用Image.FromStreamthis way
  • 乍一看,这可能就是我要找的东西。我试试看。
  • 另外,您也不需要在关闭表单后处理它。如果是对话框形式,请在 using 块中使用,否则根本不需要使用 this.Dispose。你可能想看看这个帖子Do I need to Dispose a Form after the Form got Closed?
  • 完美运行。我还更新了 ShowDialog 调用以使用 using 块正确处理
  • 仅供参考,您收到该错误的事实意味着您的 Image 对象没有被释放(至少在 GC 决定打扰它们之前)。这实际上是 GDI 对象的泄漏,这是您想要避免的事情,即使它不再导致异常。我建议您在处置表单时明确处置所有图像。

标签: c# winforms file-io dispose


【解决方案1】:

在执行@RezaAghaei 的建议后已解决问题。将预览表单更改为:

foreach (FileInfo files in folder.GetFiles())
{
    System.Diagnostics.Debug.Print(files.Extension);
    if ((string.Equals(files.Extension, ".jpg", StringComparison.OrdinalIgnoreCase)) || (string.Equals(files.Extension, ".gif", StringComparison.OrdinalIgnoreCase)) || (string.Equals(files.Extension, ".png", StringComparison.OrdinalIgnoreCase)))
    {
        using (var stream = new FileStream(files.FullName, FileMode.Open))
        {
            PictureBox image = new PictureBox();
            image.Image = Image.FromStream(stream);
            image.SizeMode = PictureBoxSizeMode.Zoom;
            image.Size = this.Size;
            imagePanel.Controls.Add(image);
        }
    }
}

我还通过实现 using 块提高了 ShowDialog 调用的效率:

using (frmPreviewPhotos frm = new frmPreviewPhotos(NEWphotoFileNameArray, lblParcel.Text))
{
    frm.ShowDialog();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 2013-05-25
    • 2016-12-22
    • 1970-01-01
    • 2016-12-13
    • 2018-06-30
    相关资源
    最近更新 更多