0

so i made a simple project where when i click a button the picture edit get an image from a folder file, but when i want to delete the folder that contains the image, it gives me an error. the code as following

 private void button1_Click(object sender, EventArgs e)
    {
        string pathx = AppDomain.CurrentDomain.BaseDirectory + "\\TempImage\\" + "naruto" + ".png";
        pictureEdit1.Image = Image.FromFile(pathx);
    }

    private void button2_Click(object sender, EventArgs e)
    {
        string dir = AppDomain.CurrentDomain.BaseDirectory + "\\TempImage";
        try {
            if (Directory.Exists(dir))
            {
                //////give me an error in here///////
                Directory.Delete(dir, true);
            }
            else
            {
                MessageBox.Show("folder not found");
            }
        }
        catch (Exception ex)
            {
            MessageBox.Show(ex.Message);
        }

    }

enter image description here

the purpose of this, is in my main project, for cache purpose. so i get an image from a certain folder after coping it from server to local. and when i want to close the main project i need to clear the cache or folder

Update

which is better alternate 1 or alternate 2 (to dispose)

   private void button1_Click(object sender, EventArgs e)
    {
        string pathx = AppDomain.CurrentDomain.BaseDirectory + "\\TempImage\\" + "naruto" + ".png";

        //alternate1
        using (FileStream stream = new FileStream(pathx, FileMode.Open, FileAccess.Read))
        {
            pictureEdit1.Image = Image.FromStream(stream);
            //stream.Dispose();
        }

        //alternate2
        //Image img = new Bitmap(pathx);
        //pictureEdit1.Image = img.GetThumbnailImage(pictureEdit1.Width, pictureEdit1.Height, null, new IntPtr());
        //img.Dispose();

    }
chopperfield
  • 559
  • 1
  • 7
  • 25
  • 1
    Possible duplicate of [IOException: The process cannot access the file 'file path' because it is being used by another process](http://stackoverflow.com/questions/26741191/ioexception-the-process-cannot-access-the-file-file-path-because-it-is-being) – Koby Douek Apr 13 '17 at 06:09
  • Maybe because you are showing it in the preview window and thus it is being accessed. You can not delete it if it is being used? – Icewine Apr 13 '17 at 06:11
  • 1
    @chopperfield the "problem" is that GDI+ image keeps the file open. Dispose it before you try to delete the file or simply read the file as a byte[] and build the image from a MemoryStream – Adriano Repetti Apr 13 '17 at 06:11

1 Answers1

1

The documentation on System.Drawing.Bitmap (http://msdn.microsoft.com/en-us/library/0cbhe98f.aspx) says:

The file remains locked until the Bitmap is disposed.

To get around this, you should replace this line:

pictureEdit1.Image = Image.FromFile(pathx);

With this:

Image img = new Bitmap(pathx);
pictureEdit1.Image = img.GetThumbnailImage(pictureEdit1.Width, pictureEdit1.Height, null, new IntPtr());
img.Dispose();

This should load the Bitmap only long enough to create a thumbnail version of the image for use in the PictureBox control, then dispose of it immediately, releasing the lock on the file but still displaying the image on the screen.

Hope this helps!

Edit: Here's the version using using that does the same thing:

using (Image img = new Bitmap(pathx)) {
  pictureEdit1.Image = img.GetThumbnailImage(pictureEdit1.Width, pictureEdit1.Height, null, new IntPtr());
}
Lusid
  • 4,518
  • 1
  • 24
  • 24
  • hi lusid, it works fine. but i want to ask now iam using `using (FileStream stream = new FileStream(pathx, FileMode.Open, FileAccess.Read)) {stream.dispose}` is it the same ? – chopperfield Apr 13 '17 at 06:39
  • Actually, the **using** statement in C# automatically calls dispose on the object you are using when the block ends, so you don't need **Dispose()** in either case if you use **using**. With that said, I personally wouldn't use a FileStream here if all you are trying to do is load the data into memory for display, but you can. – Lusid Apr 13 '17 at 06:46
  • from what you said, is that when iam using `using` statement to display iamge, its using memory for display , but with bitmap not using memory. is it? but at the end of block `using` its automatically call dispose. so it should not be using memory to display.. correct me if iam wrong – chopperfield Apr 13 '17 at 06:59
  • In your original Image.FromFile call, it would create a Bitmap object and assign that directly to the PictureBox, holding the lock on the file. All I did was use GetThumbnailImage to clone the data (using less memory btw since it is cloning it at the exact size needed for the pb), then disposed the original since it was no longer needed. The new Image created had no connection to the file in any way. That is the only thing that is important here. As long as you aren't using the original Bitmap/Image loaded from a file, you are fine. – Lusid Apr 13 '17 at 07:11
  • sory to bother you one more time, as you can see iam the update code. is it secure or the same as you are proposing?. and iam not using `fromfile` instead of stream in alternate 1 – chopperfield Apr 13 '17 at 07:44
  • It will work, but it breaks the Bitmap that is attached to the pb. So if you try to save, etc later, you will experience issues. Better to create an entirely new Bitmap that isn't connected to the file (again, the important part is cloning before attaching, not how you load the data). Please reference the comments in this issue: http://stackoverflow.com/questions/4803935/free-file-locked-by-new-bitmapfilepath/8701748#8701748 – Lusid Apr 13 '17 at 07:48