2008-11-10 53 views
3

我正在使用.net filewatcher監視某個文件(*。mbxml)的文件夾。我正在使用爲它創建的filewatcher事件。一旦創建的事件觸發,我必須將此文件移動到另一個文件夾。這種方法的問題在於,一旦文件複製開始,創建的事件就會被觸發。因此,如果文件複製到正在觀看的文件夾時間過長,則移動文件的代碼將失敗。我搜索了,我在網上找到的唯一解決方案是,您將文件移動到try-catch塊中,並繼續嘗試複製整個文件。我不喜歡這個解決方案,如果創建的事件在整個文件複製完成或者有單獨的事件發生時被解僱,情況會更好。是否有另一種方法來實現這一點?Filewatcher創建事件

回答

2

我還沒有看到這樣做,除了try catch塊。通常在oncreate事件我設置一個布爾,試圖打開文件。這決定了代碼的其餘部分是否繼續,如果有另一種方式我也會感興趣。

private static bool creationComplete(string fileName) 
    { 
     // if the file can be opened it is no longer locked and now available 
     try 
     { 
      using (FileStream inputStream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.None)) 
      { 
       return true; 
      } 
     } 
     catch (IOException) 
     { 
      return false; 
     } 
    } 
2

你能改變正在創建文件的程序嗎?如果是這樣,請將其更改爲在一個文件夾中創建它們,然後將它們(以原子方式)移動到不同的文件夾 - 或使用不同的擴展名(真正可以跟蹤的任何內容)。

1

您是否嘗試過使用BinaryReader和BinaryWriter移動文件?您可以在複製文件時讀取該文件,並將其寫入較慢的速度,以便您的移動速度不會超過其他進程創建文件的速度。您也可以在讀取之間插入一些等待時間。一旦你做了最後一次閱讀並確認文件創建完成,你可以刪除它。

祝你好運!

1

使用try/catch解決方案的全部原因是因爲知道其他程序是否完成寫入文件的唯一方法是用於文件open()調用SUCCEED。這是一個FAILURE是文件仍在寫入的定義。

通常在你的情況下,一個while()循環與一個thread.sleep定時器一起使用,它不斷地嘗試,直到A)超時或B)成功。

0

如果我沒有記錯,FileWatcher會在給定的文件/文件夾中爲每個IO引發幾個事件。您可能能夠縮小與完成關聯的FileSystemEventArgs。可能有必要延遲檢查文件是否可訪問,但我認爲這不是一個理想的解決方案。

2

來源: http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx

「共同文件系統,當文件從一個目錄移動到另一個,幾個調用onChanged和一些OnCreated和OnDeleted事件可能引發的操作可能會引發多個事件。例如,。移動文件是一個複雜的操作,由多個簡單操作組成,因此引發多個事件。同樣,某些應用程序(例如防病毒軟件)可能會導致FileSystemWatcher檢測到的其他文件系統事件。「

時間敏感您是否需要移動文件?

如果您不喜歡嘗試移動它,捕捉異常並重復直到獲得成功的想法,則可採取稍微不同的方法。

一旦你收到一個創建的事件,你開始監視文件的最後寫入時間。一旦自上次寫入時間過去了一段時間,比如兩秒鐘,您就可以嘗試移動文件。你可能會發現「失敗」的舉動少了很多,但最終的結果是一樣的。

2

觀察上創建的事件,但等待上次寫入時間更改事件。當文件完成複製時,最後的寫入時間會更新。由於您正在移動文件,因此您可能只需處理最後一次寫入時間更改事件。

3

你可以使你的代碼由FileSystemWatcher的只是繼承和fireing自己FileReady事件,像這樣簡單:

public class CustomFileSystemWatcher : System.IO.FileSystemWatcher 
{ 
    public CustomFileSystemWatcher() 
    { 
     this.Created += new FileSystemEventHandler(CustomFileSystemWatcher_Created); 
    } 


    private void CustomFileSystemWatcher_Created(object sender, FileSystemEventArgs e) 
    { 
     ThreadPool.QueueUserWorkItem((n) => { WaitFileReady(e); }); 
    } 

    private void WaitFileReady(FileSystemEventArgs e) 
    { 
     while (true) 
     { 
      try 
      { 
       using (FileStream fs = File.Open(e.FullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
       { 
        //exit 
        break; 
       } 
      } 
      catch (Exception) 
      { 
       //wait if you like 
       Thread.Sleep(100); 
      } 
     } 
     OnFileReady(e); 
    } 

    public event FileSystemEventHandler FileReady; 

    protected virtual void OnFileReady(FileSystemEventArgs e) 
    { 
     if (this.EnableRaisingEvents && FileReady != null) FileReady(this, e); 
    } 
} 
+0

你的代碼是基本相同的方法,你剛剛編寫的代碼在你的繼承類。 – Raminder 2008-11-11 08:12:34