等待系统删除文件

删除文件后刷新文件列表时遇到问题。 当我命令删除文件时,抛出了exception,因为刷新方法试图访问应该删除的文件。

经过一番思考和调试后,我得出结论,问题在于系统需要一些时间来删除文件。 我这样解决它:

//Deleting file System.Threading.Thread.Sleep(2000); //Refreshing list 

它工作得很好。

我的问题是

是否有更优雅的方式等待系统删除文件然后继续代码…?

我能想到的最优雅的方法是使用FileSystemWatcher并订阅它的Deleted事件。

这对我有用:

 public static void DeleteFile(String fileToDelete) { var fi = new System.IO.FileInfo(fileToDelete); if (fi.Exists) { fi.Delete(); fi.Refresh(); while (fi.Exists) { System.Threading.Thread.Sleep(100); fi.Refresh(); } } } 

我发现大多数时候,不会输入while循环。

轻量级代码使用FileSystemWatcher ,订阅其Deleted事件并等待。

 void DeleteFileAndWait(string filepath, int timeout = 30000) { using (var fw = new FileSystemWatcher(Path.GetDirectoryName(filepath), Path.GetFileName(filepath))) using (var mre = new ManualResetEventSlim()) { fw.EnableRaisingEvents = true; fw.Deleted += (object sender, FileSystemEventArgs e) => { mre.Set(); }; File.Delete(filepath); mre.Wait(timeout); } } 

以下是使用FileWatcher的一些代码。 我们希望能够做到的是

 await Utils.DeleteDirectoryAsync("c:\temp\foo", recurse: true); 

以下实现它

 using System; using System.IO; using System.Reactive; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Threading.Tasks; namespace Utils { internal class FileWatcher : IDisposable { readonly FileSystemWatcher _Watcher; public Subject Changed = new Subject(); public FileWatcher( string file ) { // Create a new FileSystemWatcher and set its properties. _Watcher = new FileSystemWatcher { Path = Path.GetDirectoryName(file), NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName, Filter =Path.GetFileName(file) }; // Add event handlers. _Watcher.Changed += OnChanged; _Watcher.Created += OnChanged; _Watcher.Deleted += OnChanged; _Watcher.Renamed += OnChanged; // Begin watching. _Watcher.EnableRaisingEvents = true; } // Define the event handlers. private void OnChanged( object source, FileSystemEventArgs e ) { Changed.OnNext(e); } public void Dispose() { _Watcher.Dispose(); } } } 

以及利用上述可观察性的一些工具。

 public static class FileUtils { public static IObservable ChangedObservable(string path) { if (path == null) return Observable.Never(); return Observable.Using(() => new FileWatcher(path), watcher => watcher.Changed); } public static Task DeleteDirectoryAsync(string path, bool recurse) { var task = new TaskCompletionSource(); if (Directory.Exists(path)) { ChangedObservable(path) .Where(f => f.ChangeType == WatcherChangeTypes.Deleted) .Take(1) .Subscribe(v => task.SetResult(Unit.Default)); Directory.Delete(path, recurse); } else { task.SetResult(Unit.Default); } return task.Task; } } 

我一直用这个:

 System.GC.Collect(); System.GC.WaitForPendingFinalizers(); 

看到这里和这里

使用Directory.Delete删除目录,特别是在NTFS上采用’递归’布尔值的重载 ,应该是从程序的角度来看的primefaces操作。 无需亲自手动递归。

Directory.Delete将在遇到的第一个错误上抛出exception。 如果要继续删除尽可能多的文件和子目录,则不应使用Directory.Delete,并应在循环内使用try / catch块编写自己的递归删除。 您可能希望这样做的一个示例是,如果您正在尝试清除临时文件,并且其中一个文件已被锁定。