0

I'm extracting a ZIP file. This ZIP contains image files and an Excel file with a product list. When articles of different sizes are listed the article refers to the same image. I copy the image file to a local folder and write the (compressed) binary data to SQL server database. So when it gets to the point where a JPG file shall be processed a second time, I get this exception, although I dispose the image object.

Worksheet ws;
string root = "C:\\images\\";
string file;
string importFolder = "C:\\import\\;
Dictionary <string, object> ins;

Image im;
Image th;

//Worksheet has been opened before
//ZIP has been extracted before to C:\import\

for (i = 2; i <= ws.Dimension.End.Row; i++) {
  ins = new Dictionary<string, object>(); //Dictionary to write data to database
  file = ws.Cells[i, 4].Text;
  System.IO.File.Copy(importFolder + "\\" + file, root + "\\" + file, true); // <-- Here the exception is thrown in the second iteration
  im = Image.FromFile(root + "\\" + file);
  im = im.GetBetterThumbnail(1024);
  byte[] im_data = im.GetJpgByteArray(85);
  ins.Add("url", "www.test.de/images/" + file);
  ins.Add("image_data", im_data);
  ins.Add("image_size", im_data.Length);
  //image will be written to database
  
  im.Dispose();
  im = null;
  im_data = null;
  //With these initializations there shouldn't be thrown an exception
} // end for

What am I missing? With resetting the Image object and byte array, there shouldn't be another reference to the image file. I had a look on this

IOException: The process cannot access the file 'file path' because it is being used by another process

but I couldn't figure out, how to adept to my topic. Yes, I could store all file names just to copy them once, but I think that's the lazy way.

Kind regards

  • I would recommend to avoid storing temporary data on disk unless absolutely necessary. All good APIs support taking streams instead of filenames, so you should be able to keep data in memory instead of reading previously written data. File systems tend to be a source of errors, so it is prudent to avoid it when you can. – JonasH Oct 12 '22 at 09:56
  • If there is no other solution, it can sometimes be useful to just catch the exception, wait a short while, and try again a few times. – JonasH Oct 12 '22 at 09:58

2 Answers2

1

You assign a value to the variable im two times.

One time you use im = Image.FromFile(root + "\\" + file) and the other time you use im = im.GetBetterThumbnail(1024). Could it be that this opens two handles that need to be closed?

Besides, it's better to use the using statement. Then you don't have to take care of the disposing by yourself.

For example like this:

for (i = 2; i <= ws.Dimension.End.Row; i++) 
{
  ins = new Dictionary<string, object>(); //Dictionary to write data to database
  file = ws.Cells[i, 4].Text;
  System.IO.File.Copy(importFolder + "\\" + file, root + "\\" + file, true); 

  using (im = Image.FromFile(root + "\\" + file))
  {
    // I guess that this method creates its own handle 
    // and therefore also needs to be disposed.
    using (thumbnail = im.GetBetterThumbnail(1024))
    {
      byte[] im_data = thumbnail.GetJpgByteArray(85);
      ins.Add("url", "www.test.de/images/" + file);
      ins.Add("image_data", im_data);
      ins.Add("image_size", im_data.Length);
      //image will be written to database
    }
  }
} // end for
Caveman74
  • 127
  • 9
0

I got the issue solved by using a stream. The memory management works really better now. New code:

//im = Image.FromFile(root + "\\" + file);
im = Image.FromStream(File.Open(root + "\\" + file, FileMode.Open));

So could it be that this is another 'Microsoft feature'?