哪一行代码仍在使用该文件,而不是释放它?

我正在使用这段代码来创build一个Excel文件并用数据填充它:

using (ExcelPackage package = new ExcelPackage(fileInfo)) { ExcelWorksheet ws = package.Workbook.Worksheets.Add("Deltas"); ExcelWorksheet ws2 = package.Workbook.Worksheets.Add("Images"); ExcelWorksheet ws3 = package.Workbook.Worksheets.Add("Data Points"); GenerateDataSheet(ws, true); GenerateDataSheet(ws3, false); // populate second worksheet with images var imagesLocations = SelectedSession.GetTests().Where(t => t.IsReference).Select(t => t.Location).OrderBy(t => t.DateCreated).ThenBy(t => t.Name).ToList(); ws2.Column(2).Width = 58; for (int i = 0; i < imagesLocations.Count; i++) { ws2.Row(i + 1).Height = 305; ws2.Cells[i + 1, 1].Value = imagesLocations[i].Name; ws2.Cells[i + 1, 1].Style.VerticalAlignment = ExcelVerticalAlignment.Top; ws2.Cells[i + 1, 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.Right; var imagePath = imagesLocations[i].Tests.FirstOrDefault(t => t.IsReference).ImagePath; if (File.Exists(imagePath)) { var ImageToPutInReport = Image.FromFile(imagePath); var image = ws2.Drawings.AddPicture(imagesLocations[i].Name, ImageToPutInReport); image.SetSize(375, 375); image.SetPosition(i, 0, 1, 0); } } package.SaveAs(fileInfo); } 

完成后,我调用一个函数来删除图像文件夹。 “delete()”函数popup一个错误:

图像仍在使用中

当我评论上面的代码时,错误不会发生。 目前我正在使用这个黑客来解决我的问题:

 public static void DeleteSessionFolder(string session) { try { if (Directory.Exists(baseSessionPath + session)) Directory.Delete(baseSessionPath + session, true); // error pops here } catch (Exception e) { DeleteSessionFolder(session); // call it again } } 

所以我给了一次机会不断尝试。 但是这样做需要15秒钟,直到“那东西”释放图像,应用程序能够删除文件夹,而整个应用程序被冻结。 哪一行代码保留图像(图像)?

而不是使用Image.FromFile来获取图像,你应该使用stream来读取图像的副本,然后使用这个副本进行操作。 Image.FromFile的问题是,它通过引用打开你的图像文件,所以在应用程序停止使用它之前,没有其他操作可以写入它。 它基本上是一个stream,直到它完全超出范围或手动.Dispose()的图像对象.Dispose()closures。

所以,改变这一行:

 var ImageToPutInReport = Image.FromFile(imagePath); 

到这一行:

 Image ImageToPutInReport; using (FileStream stream = File.OpenRead(imagePath)) { ImageToPutInReport = Image.FromStream(stream); } 

从这个链接Image.FromFile(string filename)它说, The file remains locked until the Image is disposed. 而且你不会在任何地方展示图片。

这是什么导致你的问题。

这一行:

 var ImageToPutInReport = Image.FromFile(imagePath); 

将你的图像打开并locking,直到你处理它(这是因为你没有明确地做,直到垃圾收集器决定:那些应该是你重试时观察的15秒)…所以, d将该块更改为:

 using(var ImageToPutInReport = Image.FromFile(imagePath)) { var image = ws2.Drawings.AddPicture(imagesLocations[i].Name, ImageToPutInReport); image.SetSize(375, 375); image.SetPosition(i, 0, 1, 0); } 

您需要确保Image对象被复制到电子表格中,否则,您将需要稍后处理它们,但应该是这样的,您将看到GC行为。

PS:正如我上面提到的,正如@ScottChamberlain在评论中指出的,图像可能被添加为引用(而不是作为一个副本),所以你会丢弃集合中引用的图像。 如果是这种情况 ,我们可以通过创build一个副本(这应该释放文件)来解锁文件,然后在完成我们的包之后处理该副本…如下所示:

 var imageList = new List<Image>(); using (ExcelPackage package = new ExcelPackage(fileInfo)) { /* ... */ if (File.Exists(imagePath)) { Image ImageToPutInReport; // Make a copy of the loaded image and dispose the original // so the file is freed using(var tempImage = Image.FromFile(imagePath)) ImageToPutInReport = new Bitmap(tempImage); // Add to the list of images we'll dispose later // after we're done imageList.Add(ImageToPutInReport); var image = ws2.Drawings.AddPicture(imagesLocations[i].Name, ImageToPutInReport); image.SetSize(375, 375); image.SetPosition(i, 0, 1, 0); } /* ... */ package.SaveAs(fileInfo); } foreach(var img in imageList) img.Dispose(); imageList.Clear();