picture is used by another process (layoutpanel)

你。 提交于 2019-12-11 16:04:54

问题


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 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;
                        }
                    }
                }
            }
     }

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.

Any ideas on this?


回答1:


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.

(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.)


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;

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.


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);

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.)



来源:https://stackoverflow.com/questions/49610796/picture-is-used-by-another-process-layoutpanel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!