Exception: Parameter is not valid (on passing new

2019-01-27 17:28发布

问题:

I already had an image inside PictureBox control, and now I want to pass a new one to it.

What happens, is that allpication Disposes (and I catch an exception: "Parameter is not valid").

This is my code:

            using (Image img = Image.FromFile(open.FileName))
            {
                part.Picture = img;
                pictureBox1.InitialImage = null;
                pictureBox1.Image = img;
            }    

So when the code goes out of the method, it goes streight to Displose of this and main form. I catch the exception only on line where Form1 was started. On this one there is no excpetions what so ever. It must be something wrong while pictureBox is painting (inside Paint event), but I am not surbsribed to it.

I really dont have any more clue how to salve this issue. I have even tried to use to clear all resources (by calling garbage collection), but nothing seems to work.


One more thing: "part" is a reference of the List, so when I try to Delete the current image (to replace it with a new one) I got another exception, like:

"The process cannot access the file because it is being used by another process".


Does this has something to do with the 1st exception (when new image is not painted in pictureBox)?

回答1:

As Reed noted, the Image you are pulling from open.Filename is being disposed once you exit the using() statement. Your picturebox is still referencing this image in memory, so when it is disposed, you lose what was stored in your picturebox too.

What you really need is a unique copy of the image you are pulling.

    using (Image sourceImg = Image.FromFile(open.Filename))
    {
        Image clonedImg = new Bitmap(sourceImg.Width, sourceImg.Height, PixelFormat.Format32bppArgb);
        using (var copy = Graphics.FromImage(clonedImg))
        {
            copy.DrawImage(sourceImg, 0, 0);
        }
        pictureBox1.InitialImage = null;
        pictureBox1.Image = clonedImg;
    }

This way, your file will be unlocked as soon as you exit this block, and you'll keep a unique copy of your image in the picturebox.



回答2:

The problem is that, after this code executes, pictureBox1.Image is referring to an Image which has been disposed.

If you do not wrap the Image creation in a using, it should correct your issue.

Image img = Image.FromFile(open.FileName);
part.Picture = img;
pictureBox1.InitialImage = null;
pictureBox1.Image = img; // You can't dispose of this, or it won't be valid when PictureBox uses it!


回答3:

You could also do something like the following create a method that loads the images and then pass it back to the Image Control for example this is what I am using when I want to populate an Image Ctrl

I have a windows form with 3 different Images that I want to load but I am only showing the code for One since I call the same method for all 3 Image Controls

    #region Codes for browsing for a picture
    /// <summary>
    /// this.picStudent the name of the Image Control
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnStudentPic_Click(object sender, EventArgs e)
    {
        Image picture = (Image)BrowseForPicture();
        this.picStudent.Image = picture;
        this.picStudent.SizeMode = PictureBoxSizeMode.StretchImage;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    private Bitmap BrowseForPicture()
    {
       // Bitmap picture = null;

        try
        {
            if (this.fdlgStudentPic.ShowDialog() == DialogResult.OK)
            {
                byte[] imageBytes = File.ReadAllBytes(this.fdlgStudentPic.FileName);
                StudentPic = new Bitmap( this.fdlgStudentPic.FileName);
                StuInfo.StudentPic = imageBytes;
            }
            else
            {
                StudentPic = Properties.Resources.NoPhotoAvailable;
            }
        }
        catch (Exception)
        {
            MessageBox.Show("That was not a picture.", "Browse for picture");
            StudentPic = this.BrowseForPicture();
        }

        return StudentPic;
    }
    #endregion


回答4:

Yes, this is now working, but strange, I would almost swear I tried this way too. Ok, never mind, just that it works. What is troubling me is something else too, which is in my opinion the same as your code, but its not working, its again trying to Dispose application (with same exception). This is an example code:

using(Image img = Image.FromFile(open.FileName))
{
   part.Picture = img; 
}
pictureBox1.InitialImage = null;
pictureBox1.Image = part.Picture;  //Picture  is a propery in a class

Now I pass an actual image into a generic list, and try to assign new image to pictureBox from it, but, again as I said, exception is thrown (and application is terminated). Why?



标签: c# image dispose