2010-08-08 177 views
2

考慮以下代碼:如何使用FileSystemWatcher觀察目錄並仍然允許它被正確刪除?

string dir = Environment.CurrentDirectory + @"\a"; 
Directory.CreateDirectory(dir); 
FileSystemWatcher watcher = new FileSystemWatcher(dir); 
watcher.IncludeSubdirectories = false; 
watcher.EnableRaisingEvents = true; 
Console.WriteLine("Deleting " + dir); 
Directory.Delete(dir, true); 
if (Directory.Exists(dir)) 
{ 
    Console.WriteLine("Getting dirs of " + dir); 
    Directory.GetDirectories(dir); 
} 
Console.ReadLine(); 

有趣的是,這將引發一個UnauthorizedAccessException上Directory.GetDirectories(dir)

刪除監視的目錄無錯地返回,但是Directory.Exists()仍然返回true並且目錄仍然列出。此外訪問該目錄會產生任何程序的「訪問被拒絕」。一旦帶有FileSystemWatcher的.NET應用程序退出目錄就會消失。

我怎樣才能看到一個目錄,同時仍然允許它被正確刪除?

回答

5

你確實刪除了目錄。但是,直到引用它的最後一個句柄關閉之後,該目錄纔會從文件系統中物理刪除。任何嘗試在兩者之間打開它(就像你對GetDirectories所做的那樣)將會失敗並出現拒絕訪問錯誤。

文件存在相同的機制。回顧FileShare.Delete

+0

這是相當令人不滿意的,因爲它使無形的目錄無法觀察。但是由於它是Windows的限制,我沒有看到解決辦法。 – 2012-09-18 07:05:56

2

試試這個行:

if (new DirectoryInfo(dir).Exists) 

代替:

if (Directory.Exists(dir)) 
1

您應該使用FileSystemInfo.Refresh。之後.REFRESH().Exists顯示正確結果:

var dir = new DirectoryInfo(path); 
    // delete dir in explorer 
    System.Diagnostics.Debug.Assert(dir.Exists); // true 
    dir.Refresh(); 
    System.Diagnostics.Debug.Assert(!dir.Exists); // false 
1

不幸的是FileSystemWatcher的採取了手柄的目錄,這意味着當目錄被刪除,仍然有一個句柄標記爲待刪除的目錄。我試過一些實驗,看起來你可以使用FileSystemWatcher中的Error事件處理程序來識別發生這種情況的時間。

public myClass(String dir) 
    { 
     mDir = dir; 
     Directory.CreateDirectory(mDir); 

     InitFileSystemWatcher(); 

     Console.WriteLine("Deleting " + mDir); 
     Directory.Delete(mDir, true); 
    } 
    private FileSystemWatcher watcher; 

    private string mDir; 

    private void MyErrorHandler(object sender, FileSystemEventArgs args) 
    { 
     // You can try to recreate the FileSystemWatcher here 
     try 
     { 
      mWatcher.Error -= MyErrorHandler; 
      mWatcher.Dispose(); 
      InitFileSystemWatcher(); 
     } 
     catch (Exception) 
     { 
      // a bit nasty catching Exception, but you can't do much 
      // but the handle should be released now 
     } 
     // you might not be able to check immediately as your old FileSystemWatcher 
     // is in your current callstack, but it's a start. 
    } 

    private void InitFileSystemWatcher() 
    { 
     mWatcher = new FileSystemWatcher(mDir); 
     mWatcher.IncludeSubdirectories = false; 
     mWatcher.EnableRaisingEvents = true; 
     mWatcher.Error += MyErrorHandler; 
    } 
相關問題