How do I tell my C # application to close the file it opened in a FileInfo object, or possibly a Bitmap object?

So, I wrote a quick application to sort my wallpapers neatly into folders according to aspect ratio. Everything goes smoothly until I try to move the files (using FileInfo.MoveTo ()). The application throws an exception:

System.IO.IOException The process cannot access the file because it is being used by another process.

The only problem is that on my computer there is no other process opening this file. I thought that maybe because of the way I used the file, maybe some internal system routine in another thread or something opened the file when I try to move it. Of course, a few lines above, I set a property that raises an event that opens the file for reading. I guess at least some of them happen asynchronously. Is there a way to make it work synchronously? I have to change this property or rewrite most of the code.

Here are some relevant bits of code, please forgive the crappy Visual C # default names for things, this is not a software quality release yet:

private void button1_Click(object sender, EventArgs e) { for (uint i = 0; i < filebox.Items.Count; i++) { if (!filebox.GetItemChecked((int)i)) continue; //This calls the selectedIndexChanged event to change the 'selectedImg' variable filebox.SelectedIndex = (int)i; if (selectedImg == null) continue; Size imgAspect = getImgAspect(selectedImg); //This is gonna be hella hardcoded for now //In the future this should be changed to be generic //and use some kind of setting schema to determine //the sort/filter results FileInfo file = ((FileInfo)filebox.SelectedItem); if (imgAspect.Width == 8 && imgAspect.Height == 5) { finalOut = outPath + "\\8x5\\" + file.Name; } else if (imgAspect.Width == 5 && imgAspect.Height == 4) { finalOut = outPath + "\\5x4\\" + file.Name; } else { finalOut = outPath + "\\Other\\" + file.Name; } //Me trying to tell C# to close the file selectedImg.Dispose(); previewer.Image = null; //This is where the exception is thrown file.MoveTo(finalOut); } } //The suspected event handler private void filebox_SelectedIndexChanged(object sender, EventArgs e) { FileInfo selected; if (filebox.SelectedIndex >= filebox.Items.Count || filebox.SelectedIndex < 0) return; selected = (FileInfo)filebox.Items[filebox.SelectedIndex]; try { //The suspected line of code selectedImg = new Bitmap((Stream)selected.OpenRead()); } catch (Exception) { selectedImg = null; } if (selectedImg != null) previewer.Image = ResizeImage(selectedImg, previewer.Size); else previewer.Image = null; } 

I have a long fix (which is probably more efficient anyway), but these are even more problems: /

Any help would be greatly appreciated.

+4
source share
3 answers

Since you use selectedImg as a variable with the scope of the class, it locks the file while the bitmap is open. I would use using statement , and then Clone bitmap into the variable that you are using will release the lock that Bitmap stores in the file.

Something like that.

 using ( Bitmap img = new Bitmap((Stream)selected.OpenRead())) { selectedImg = (Bitmap)img.Clone(); } 
+1
source

New answer:

I looked at the line where you are doing OpenRead (). Obviously, this locks your file. It would be better to specify the path to the file instead of the stream, because you cannot control the stream, because the bitmap will become erroneous.

Another thing I'm looking for in your code that might be bad practice is binding to FileInfo. It’s better to create an object of an object / data transmission object and bind it to a collection of this type - some object that has the properties that you need to show in your control. This will help to avoid file locks.

On the other hand, you can do some trick: why don't you show compressed images with a screen resolution that compresses them, so the image size will be extremely lower than the actual ones, and you provide the "Show in HQ" button? This should solve the problem of preloading HD images. When the user clicks the "Show in HQ" button, loads this image into memory, and when it is closed, it becomes deleted.

Is it OK for you?

If I am not mistaken, FileInfo does not block any file. You do not open it, but read its metadata.

On the other hand, if the application displays images, you must transfer them to visible ones in memory and load them into your form from the memory stream.

This is reasonable because you can open the file stream, read its bytes and transfer them to the memory stream, leaving the file locked.

NOTE. This solution is great for not-so-large images ... Let me know if you work with HD images.

0
source
 using(selectedImg = new Bitmap((Stream)selected)) 

Will it do it?

0
source

Source: https://habr.com/ru/post/1335843/


All Articles