C# How to dispose of OpenFileDialog file

1.6k Views Asked by At

I use OpenFileDialog to get the path of an image and then set it to my image source property imgSelected.Source = new BitmapImage(new Uri(filenameSteg, UriKind.Absolute)); in a WPF application.

The thing is, I need to open that file again later but I can't open it since the file is being used by another process ( System.IO.IOException -> The process cannot access the file pathToFile because it is being used by another process.).

The code that needs to access it later it as follow :

 bitmapSource = JpegBitmapDecoder.Create(File.Open(filenameSteg, FileMode.Open),
                BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames[0];

This bitmapSource is used to give that image to a WriteableBitmap and from there I go through the pixels.

Is there any way to dispose of a File opened with an OpenFileDialog ?

I tried to cast to to IDisposable, to use a using block and so on but this thing is persistent.

EDIT :

1 - I tried this (@ctacke answer) :

 using (var stream = File.Open(filenameSteg, FileMode.Open)){
        bitmapSource = JpegBitmapDecoder.Create(stream, BitmapCreateOptions.None,
        BitmapCacheOption.OnLoad).Frames[0];}

But it still gives me the error about the process being already in used by another process because even though it will be disposed after, I still am trying to open the same file (filenameSteg) than I opened in the OpenFileDialog. (Or at least, that's how I see it.)

2 - I then tried this (based on @ctacke recommended link:

using (FileStream fileStream = new FileStream(filenameSteg+1, FileMode.Create)){
       MemoryStream memoryStream = new MemoryStream();
       BitmapImage bi = new BitmapImage();
       byte[] fileBytes = File.ReadAllBytes(filenameSteg);
       memoryStream.Write(fileBytes, 0, fileBytes.Length);
       memoryStream.Position = 0;

       bi.BeginInit();
       bi.StreamSource = memoryStream;
       bi.EndInit();

       bitmapSource = bi;}

Note : Notice that I here ask for filenameSteg +1. That is because I wanted to test the rest of my method so I create a copy the file and simply added a 1 to its name. That being said, when using filenameSteg for real, it gave me the same error about being already in used which I again suspect is that I still am asking to open the same image that was previously opened in the OpenFileDialog.

3 - I thought of another approach which does not require me to dispose the opened image :

When I open the image for the first time in the OpenFileDialog, I store the byte array of the image in a variable so I could create the WriteableBitmap using the BitmapFactory and the byte array.

// This is in the OpenFileDialog. It is where I stock the image "pixels" in a byte array.
bytesArrayImage = File.ReadAllBytes(filenameSteg); 
//And then later when I needed the WriteableBitmap, I used the byte array and the BitmapFactory
//imgSelected being the Image containing the image I opened in the OpenFileDialog, I used it's
//width and height 
wb = BitmapFactory.New(Convert.ToInt32(imgSelected.Width),
     Convert.ToInt32(imgSelected.Height)).FromByteArray(bytesArrayImage);

The problem with this approach is that, some pictures works fine and I can use the byte array to create the WriteableBitmap and go through it's pixels but in other cases it gives me an AccessViolationException stating : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.. In other words, trying to bypass the dispose problem got me into another problem.

1

There are 1 best solutions below

1
On

You should release the original image, something like this:

if(imgSelected.Source != null)
{
    imgSelected.Source.Dispose;
}
imgSelected.Source = new BitmapImage(new Uri(filenameSteg, UriKind.Absolute));

Next, File.Open returns a stream, which you need to explicitly release.

using(var stream = File.Open(filenameSteg, FileMode.Open))
{
    var bitmapSource = JpegBitmapDecoder.Create(stream,
        BitmapCreateOptions.None, BitmapCacheOption.OnLoad).Frames[0];
}

See also: Load a BitmapSource and save using the same name in WPF -> IOException