删除正在被其他进程使用的文件

44
我正在尝试以编程方式删除一个文件,但是该文件显然正在被另一个进程使用(这恰好是我的程序)。基本上,该程序通过使用FromUri从文件夹加载图像创建位图,然后将其加载到图像数组中,该数组又成为stackpanel的子元素。效率不高,但能用。
我已经尝试清除stackpanel的子元素,并使数组中的图像为空,但仍然收到IOException告诉我该文件正被另一进程使用。
是否有其他方法可以从我的应用程序进程中删除该文件?

1
你是否正在处理图像?将它们设置为null意味着它们的句柄直到被垃圾回收之前都不会被关闭。 - gotopie
4
请展示你加载它们的代码。如果存在悬空引用,它们仍将保持打开状态。 - Simon Whitehead
7个回答

145

可能是垃圾回收问题。

System.GC.Collect(); 
System.GC.WaitForPendingFinalizers(); 
File.Delete(picturePath);

3
令人恼火的是,这实际上起作用了。尝试了其他所有方法,包括“重试模式”,但只有这两行代码才可行。 - TEK
它也帮助了我。谢谢。 - Devsainii
谢谢!这也帮助了我! - oopsdazie
2
如果这个答案对你有用,那很可能是因为你没有关闭一个 FileStream。垃圾回收器会调用终结器 ~FileStream(),然后调用它自己的 Dispose() 方法,最终释放文件句柄(参见源代码)。 - Mike
它帮助了我,节省了我的时间。 - mandarin software
显示剩余2条评论

29

要在加载后释放图像文件,您需要通过设置BitmapCacheOption.OnLoad标志来创建图像。一种方法是这样的:

string filename = ...
BitmapImage image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(filename);
image.EndInit();

尽管在从本地文件Uri加载的BitmapImage上设置BitmapCacheOption.OnLoad有效,但据我所知,这并未得到记录。因此,可能更好或更安全的方法是通过设置StreamSource属性而不是UriSource来从FileStream加载图像:

string filename = ...
BitmapImage image = new BitmapImage();

using (var stream = File.OpenRead(filename))
{
    image.BeginInit();
    image.CacheOption = BitmapCacheOption.OnLoad;
    image.StreamSource = stream;
    image.EndInit();
}

14

另一种方法是删除文件。使用FileStream类加载文件,然后通过stream.Dispose()释放文件,这样就不会出现“由于其他进程正在使用此文件,因此无法访问该文件”异常。

using (FileStream stream = new FileStream("test.jpg", FileMode.Open, FileAccess.Read))
{
    pictureBox1.Image = Image.FromStream(stream);
     stream.Dispose();
}

 // delete your file.

 File.Delete(delpath);

看起来,如果您稍后尝试操作、克隆甚至保存其图像,则可能会引发异常。 - Nyerguds

4
var uploadedFile = Request.Files[0]; //Get file
var fileName = Path.GetFileName(uploadedFile.FileName);  //get file name
string fileSavePath = Server.MapPath(fileName); //get path
uploadedFile.SaveAs(fileSavePath); //saving file
FileInfo info = new FileInfo(fileSavePath);//get info file
//the problem ocurred because this, 
FileStream s = new FileStream(fileSavePath, FileMode.Open); //openning stream, them file in use by a process
System.IO.File.Delete(fileSavePath); //Generete a error
//problem solved here...
s.Close();
s.Dispose();
System.IO.File.Delete(fileSavePath); //File deletad sucessfully!

-1

我曾经遇到过类似的问题。唯一的区别是我在使用Binding(MVVM模式)。尝试了很多方法都没有效果,直到我把所有东西都移除,并尝试使用 Mode=OneWay绑定方式,以及在调用 File.Delete(path) 之前加上 GC.Collect() 命令,最终问题得到解决。


-1

我遇到了同样的问题。我的问题是 openFileDialog 和 saveFileDialog 的以下设置:

MyDialog.AutoUpgradeEnabled = false;

我注释掉了那一行,问题得到了解决。


-2
在我的情况下,我启动了一个新的 devenv.exe 进程,打开了一个临时解决方案文件。 在进程结束后,我发现我无法删除该目录几分钟。 使用 "resmon" (资源监视器) 检查后,我发现有一个叫做 PerfWatson2.exe 的可执行文件正在使用这个临时文件。 查看 网站 ,PerfWatson 实际上是 MicroSoft 的 Visual Studio 客户体验改进计划。即使您已经结束了 VS IDE,在您暂时使用的文件或目录上锁定它。 解决方法是禁用 Visual Studio 客户体验改进程序,请参见 此处。 在应用程序发布后,这将不会成为问题。 但在调试过程中相当令人恼火。

这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - Karl Stephen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接