【问题标题】:Delete an image being used by another process删除正在被另一个进程使用的图像
【发布时间】:2019-06-15 14:50:32
【问题描述】:

我正在用 C# 编写一个 winform 应用程序来打开一个图像并在其上覆盖另一个图像。

底部的图像是 .jpg,顶部的图像是从 .svg 转换而来的 .bmp。 .jpg 和 .svg 是我想要保留在文件夹中的唯一文件。 .bmp 用作临时文件。

我使用以下代码覆盖图像。但是我无法删除 temp .bmp,因为它被另一个进程使用。我认为是这个组合代码仍然可以访问最后一个 .bmp 文件。

有人可以帮我解决这个问题吗?谢谢。

    private void buttonSearch_Click(object sender, EventArgs e)
    {
        FailInfo.Text = "";

        deletebmp(strFolderPath); 

        ...

        // Check if the specified front image exists. Yes, show the file name and convert SVG to BMP. No, show the error msg.
        if (File.Exists(strFilePathF))
        {
            labelFront.Text = strFileNameF;
            var svgConvert = SvgDocument.Open(svgFilePathF);
            svgConvert.Draw().Save(bmpFilePathF);
            pictureBoxFront.Image = Image.FromFile(strFilePathF);
        }
        else
        {
            labelFront.Text = "Couldn't find the file!";
            pictureBoxFront.Image = null;
        }

        // Check if the specified back image exists. Yes, show the file name and convert SVG to BMP. No, show the error msg.   
        if (File.Exists(strFilePathBF))
        {
            labelBack.Text = strFileNameBF;
            strFilePathB = strFilePathBF;
            pictureBoxBack.Image = Image.FromFile(strFilePathB);
            labelResult.Text = "FAIL";
            labelResult.BackColor = Color.FromArgb(255, 0, 0);
            var svgConvert = SvgDocument.Open(svgFilePathBF);
            bmpFilePathB = strFolderPath + strFileNameBF + ".bmp";
            svgConvert.Draw().Save(bmpFilePathB);
            svgFilePathB = svgFilePathBF;
            inspectionres(svgFilePathB);
            labelreason.Visible = true;
        }
        else if (File.Exists(strFilePathBP))
        {
            labelBack.Text = strFileNameBP;
            strFilePathB = strFilePathBP;
            pictureBoxBack.Image = Image.FromFile(strFilePathB);
            labelResult.Text = "PASS";
            labelResult.BackColor = Color.FromArgb(0, 255, 0);
            var svgConvert = SvgDocument.Open(svgFilePathBP);
            bmpFilePathB = strFolderPath + strFileNameBP + ".bmp";
            svgConvert.Draw().Save(bmpFilePathB);
            svgFilePathB = svgFilePathBP;
            inspectionres(svgFilePathB);
            labelreason.Visible = false;
        }
        else
        {
            labelBack.Text = "Couldn't find the file!";
            pictureBoxBack.Image = null;
            labelResult.Text = "ERROR";
            labelResult.BackColor = Color.FromArgb(0, 255, 255);
            labelreason.Visible = false;
        }
    }

    //
    // Overlay the SVG file on top of the JPEG file
    //
    private Bitmap Combine(string jpegFile, string bmpFile)
    {        
        Image image1 = Image.FromFile(jpegFile);
        Image image2 = Image.FromFile(bmpFile);
        Bitmap temp = new Bitmap(image1.Width, image1.Height);

        using (Graphics g = Graphics.FromImage(temp))
        {
            g.DrawImageUnscaled(image1, 0, 0);
            g.DrawImageUnscaled(image2, 0, 0);
        }

        return temp;
    }

    //
    // Show the overlaid graphic in the picturebox
    //
    private void checkBoxOverlay_CheckedChanged(object sender, EventArgs e)
    {
        try
        {
            if (FindFront)
                if (checkBoxOverlay.Checked)
                    pictureBoxFront.Image = Combine(strFilePathF, bmpFilePathF);
                else
                    pictureBoxFront.Image = Image.FromFile(strFilePathF);
            else
                pictureBoxFront.Image = null;

            if (FindBack)
                if (checkBoxOverlay.Checked)
                    pictureBoxBack.Image = Combine(strFilePathB, bmpFilePathB);
                else
                    pictureBoxBack.Image = Image.FromFile(strFilePathB);
            else
                pictureBoxBack.Image = null;
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error loading image" + ex.Message);
        }
    }

    //
    // Option of changing the image folder
    //
    private void buttonPath_Click(object sender, EventArgs e)
    {
        FolderBrowserDialog FolderBrowserDialog1 = new FolderBrowserDialog();
        if (FolderBrowserDialog1.ShowDialog() == DialogResult.OK)
        {
            strFolderPath = FolderBrowserDialog1.SelectedPath + "\\";
        }
    }

    //
    // Pull the inspection result info from the SVG file
    //
    private void inspectionres(string filename)
    {
        XDocument document = XDocument.Load(filename);
        XElement svg_Element = document.Root;
        string sb = null;

        var faillist = (from svg_path in svg_Element.Descendants("{http://www.w3.org/2000/svg}text") select svg_path).ToList();

        foreach (var item in faillist)
        {
            sb += item.ToString();
        }
    }

    //
    // Delete all the .bmp files generated from .svg files
    //
    private void deletebmp(string path)
    {
        // Unload the images from the picturebox if applicable
        pictureBoxFront.Image = null;
        pictureBoxBack.Image = null;

        string[] files = Directory.GetFiles(path, "*.bmp");
        for (int i = 0; i < files.Length; i ++ )
            File.Delete(files[i]);
    }
}

【问题讨论】:

  • 使用你的图形对象而不是创建它,你可能不会调用 g.Dispose():using (Graphics g = Graphics.FromImage(temp)) { /* code to edit here */ } /* return here */
  • 您要删除的是 image2 吗?我没有看到您试图删除文件的任何地方?
  • @EBrown,两种方法我都试过了,没用。
  • @RonBeyer,是的,image2 是我想删除的隐藏的 .bmp 文件。删除函数只是一个简单的 File.Delete(path),它驻留在另一个我没有发布的函数中。
  • 这个文件写在哪里?您确定文件句柄已正确关闭,还是确实是您无法控制的另一个进程正在写入文件?

标签: c# svg


【解决方案1】:

Image 实现IDisposable,因此简单地将pictureBox.Image 属性设置为null 不会释放资源(在您的情况下是文件)。您的 Combine 方法也会使图像保持打开状态。在尝试删除文件之前,您必须致电 Dispose

Image image1 = Image.FromFile(path1);
File.Delete(path1);  // error - file is locked 

Image image2 = Image.FromFile(path2);
image2.Dispose();
File.Delete(path2);  // works

另一种方法(我假设您在这里使用的是 WinForms,在 WPF 中它有点不同)是手动从文件加载位图(使用 FromStream)。然后,您可以立即关闭流并删除文件:

Image image;
using (Stream stream = File.OpenRead(path))
{
    image = System.Drawing.Image.FromStream(stream);
}
pictureBox.Image = image;
File.Delete("e:\\temp\\copy1.png");  //works

【讨论】:

    【解决方案2】:

    Vesan 的回答对我没有帮助,所以我找到了不同的解决方案。 所以我可以安全/打开图像,如果我想立即删除图像。

    我将它用于我的 dataGridView_SelectionChanged:

    private void dataGridViewAnzeige_SelectionChanged(object sender, EventArgs e)
    {
        var imageAsByteArray = File.ReadAllBytes(path);
        pictureBox1.Image = byteArrayToImage(imageAsByteArray);
    }
    
    public Image byteArrayToImage(byte[] byteArrayIn)
    {
        MemoryStream ms = new MemoryStream(byteArrayIn);
        Image returnImage = Image.FromStream(ms);
        return returnImage;
    }
    

    【讨论】:

      【解决方案3】:

      以上所有答案都很好,但我有不同的方法。 使用 Image 抽象类,您不会获得很多用于操作和调整图像大小的选项。

      不如你这样做:-

       Bitmap img = new Bitmap(item);
       img.SetResolution(100, 100);
       Image imgNew = Image.FromHbitmap(img.GetHbitmap());
       pictureBox1.Image = imgNew;
       img.Dispose();
      

      【讨论】:

        猜你喜欢
        • 2017-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-12
        • 1970-01-01
        • 1970-01-01
        • 2012-10-27
        相关资源
        最近更新 更多