Search code examples
c#imagedisposeflowlayoutpanelsystem.io.file

picture is used by another process (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 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?


Solution

  • The basic rules to remember when opening images are these:

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