图片被另一个进程使用(layoutpanel) [英] picture is used by another process (layoutpanel)

查看:120
本文介绍了图片被另一个进程使用(layoutpanel)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我用以下代码填充浮动布局面板中的图像:

So i am filling a float layout panel with images, with this code:

    private void FillPanel(string sql)
    {
        panel.Controls.Clear();

        SQLiteConnection dbConnect = new SQLiteConnection("Data Source=" + dbFullPath + ";Version=3;");
        dbConnect.Open();

        SQLiteCommand runQuery = new SQLiteCommand(sql, dbConnect);
        SQLiteDataReader reader = runQuery.ExecuteReader();

        while (reader.Read())
        {              
            PictureBox pB = new PictureBox();
            pB.Image = Image.FromFile(reader["imgPath"].ToString());
            pB.Size = new Size(100, 100);
            pB.SizeMode = PictureBoxSizeMode.StretchImage;
            pB.Padding = new Padding();
            pB.Margin = new Padding(5,5,5,5);
            pB.Name = reader["name"].ToString();
            toolTip_Main.SetToolTip(pB, pB.Name);

            pB.DoubleClick += img_DoubleClick;

            panel.Controls.Add(pB);
        }
        dbConnect.Close();

    }

如果我稍后尝试删除源图片,则会收到错误消息.

And if i try to delete the source pictures later i get an errormessage.

"image.png被另一个进程使用"

"image.png is used by another process"

要删除图像,请使用以下代码:

To delete the images i use following code:

     private void Delete()
    {
            foreach (Control x in panel.Controls)
            {
                if (x is PictureBox)
                {
                    PictureBox pb = x as PictureBox;
                    string name = pb.Name;

                    DirectoryInfo pF = new DirectoryInfo(pictureFolder);
                    foreach (FileInfo file in pF.GetFiles())
                    {
                        if(file.Name == name+".png")
                        {
                            pb.InitialImage = null;
                            pb.Dispose();
                            file.Delete();
                            break;
                        }
                    }
                }
            }
     }

如果我不使用图像填充面板,则可以删除它们. 我只是不知道在'initialimage = null'&旁边我还能做什么? .dispose清除面板内的图像.

If i dont fill the panel with images, i am able to delete them. I just dont know what else i could do next to 'initialimage = null' & .dispose to getz rid of the images inside the panel.

但似乎他们在某个地方出现鬼影.

But it seems that they are ghosting somewhere.

对此有何想法?

推荐答案

打开图像时要记住的基本规则是:

The basic rules to remember when opening images are these:

  • 从文件
  • An Image object created from a file will lock the file during the life cycle of the image object, preventing the file from being overwritten or deleted until the image is disposed.
  • An Image object created from a stream will need the stream to remain open for the entire life cycle of the image object. Unlike with files, there is nothing actively enforcing this, but after the stream is closed, the image will give errors when saved, cloned or otherwise manipulated.

(如果您想知道,Image.FromFile(String filename)实际上只是new Bitmap(String filename)构造函数的包装.我个人建议不要使用Image.FromFile,因为它丢失了返回对象的更精确的Bitmap类型.)

(If you're wondering, Image.FromFile(String filename) is really just a wrapper for the new Bitmap(String filename) constructor. I personally advise not to use Image.FromFile since it loses the more precise Bitmap type of the returned object.)

关于您的问题,似乎处置PictureBox并没有处置实际的图像.这可以通过先显式设置pb.Image来解决:

As for your issue, it seems that disposing the PictureBox does not dispose the actual image. This can probably be solved by explicitly disposing pb.Image first:

Image img = pb.Image;
// Needs to happen in this order so the UI will never try to paint the disposed image
pb.Image = null;
if (img != null)
    img.Dispose();
file.Delete();
break;

请注意,放置实际的图像盒可能会导致问题;您应该先将其从其父控件中删除,以使其不再显示在UI上,否则您的窗体将开始引发对象处置"异常,因为它试图绘制的控件之一无效.

Note that disposing the actual image box can lead to problems; you should remove it from its parent control first so it no longer shows on the UI, otherwise your form will start throwing "object disposed" exceptions because one of the controls it's trying to draw is invalid.

解决锁定问题的另一种方法是从磁盘读取位图,使用new Bitmap(Image image)构造函数从中创建一个新的位图,然后处理从文件初始化的位图对象.最好的方法是使用using指令,如下所示:

Another way around the locking problem is to read the bitmap from disk, create a new bitmap out of it using the new Bitmap(Image image) constructor, and then disposing the bitmap object initialised from the file. The best way to do this is with a using directive, like this:

using (Bitmap im = new Bitmap(reader["imgPath"].ToString()))
    pB.Image = new Bitmap(im);

通常,您始终应该清理创建的图像对象.请注意,这实际上是在新的32bppARGB图像上绘制图像,从而丢失了图像的原始格式.尽管在您的情况下,我认为这无关紧要,因为无论如何它仅用于显示在UI上. (请注意,如果您确实需要图像的完整1:1数据克隆,而没有指向流或文件的任何链接,则有多种方法可以执行此操作,但是

As a rule, you should always clean up image objects you create anyway. Do note that this actually paints the image on a new 32bppARGB image, thereby losing whatever original format the image had. Though in your case I suppose that doesn't matter much, since it's just for showing on the UI anyway. (Note, if you do need a complete 1:1 data clone of an image without any links to streams or files, there are ways to do this, but they're slightly more advanced.)

这篇关于图片被另一个进程使用(layoutpanel)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆