2013-02-11 69 views
10

我有一個應用程序,在選定的文件夾中偵聽* .log文件。我用FileSystemWatcher如何等待File.Exists?

但有一個問題。負責制定該文件的其他應用程序需要以下步驟:

  1. 撥打*。廣州文件
  2. 它解壓縮到txt文件(一些隨機的文件名)
  3. 更改* .TXT名稱適當的一個帶* .log擴展名。

而且我無法改變這種行爲。

所以我製作了2 FileSystemWatcher s用於* .gz和* .txt文件。爲什麼?因爲這個應用程序有時不會解壓縮gz文件,有時不會將txt文件重命名爲最終的* .log文件。

FileSystemWatcher2捕獲txt文件,然後(在大多數情況下它被重命名爲登錄下一個1000ms)我需要等待一段時間來檢查txt文件是否存在(如果沒有,它似乎被重命名爲最終* .log文件)。

問題是,如何檢查文件是否存在沒有Thread.Sleep()以防止UI凍結?

我希望很明顯,如果不是,我會盡力描述它。我認爲這是一個複雜的問題。

一些代碼示例:

看守的GZ文件:

private void fileSystemWatcher_Created(object sender, FileSystemEventArgs e) 
{ 
    //this is for gz files in case if gz file is not unpacked automatically by other app 
    //I need to wait and check if gz was unpacked, if not, unpack it by myself, 
    //then txt watcher will catch that 
    Thread.Sleep(5000); 
    if (File.Exists(e.FullPath)) 
    { 
     try 
     { 
     byte[] dataBuffer = new byte[4096]; 
     using (System.IO.Stream fs = new FileStream(e.FullPath, 
                FileMode.Open, 
                FileAccess.Read)) 
     { 
      using (GZipInputStream gzipStream = new GZipInputStream(fs)) 
      {        
       string fnOut = Path.Combine(path_to_watcher, 
              Path.GetFileNameWithoutExtension(e.FullPath)); 

       using (FileStream fsOut = File.Create(fnOut)) 
       { 
        StreamUtils.Copy(gzipStream, fsOut, dataBuffer); 
       }        
      } 
     } 
     } 
     catch { //Ignore } 
    } 
} 

看守的txt文件:

private void fileSystemWatcher2_Created(object sender, FileSystemEventArgs e) 
{ 
    //this is for txt file 
    Thread.Sleep(3500); 
    if (File.Exists(e.FullPath)) 
    { 
     //make my actions 
    } 
    else 
    { 
     //make my actions 
    } 
} 
+0

所有'Thread.sleep代碼()'確實是放棄線程釋放它正在使用,使它們可用於其他任務的計算機資源。對於某些場景(因爲它具有1 ms的最小粒度),但對於您要實現的內容而言,它並不理想,因此它可能工作得很好。 – 2013-02-11 16:33:47

+0

@RobertHarvey你有這方面的一些文件?根據我的經驗,Thread.Sleep會阻止線程處理任何進一步的指令,直到時間過去。來自MSDN:'該線程不會被計劃在指定的時間內被操作系統執行。「# – CodingGorilla 2013-02-11 16:36:02

+0

@CodingGorilla:是的,沒錯。它阻塞並釋放線程爲其他任務持有的資源。它基本上是說「我在接下來的n毫秒內沒有做任何事情,所以你可以在那段時間去做別的事情。」 – 2013-02-11 16:38:38

回答

1

您可以使用睡眠不鎖定UI線程,你基本上是睡單獨的線程。

public event EventHandler FileCreated; 
public void CheckFileExists() 
{ 
    while(!File.Exists("")) 
    { 
    Thread.Sleep(1000); 
    } 
    FileCreated(this, new EventArgs()); 
} 

然後調用此爲:

Thread t = new Thread(CheckFileExists); 
this.FileCreated += new EventHandler(somemethod); 
t.Start(); 

public void SomeMethod(object sender, EventArgs e) 
{ 
    MessageBox.Show("File Created!"); 
} 

或在另一篇文章中提到的地方單獨的線程中使用BackGroundWorker,把我變成DoWork提到的代碼,並聆聽OnFinish事件但看到沒有太多的工作要做,兩種方法都很好。

+0

這可能更好地由'Task'或'ThreadPool.QueueUserWorkItem'處理。 – CodingGorilla 2013-02-11 16:38:48

+0

@CodingGorilla顯然這將取決於OP框架的任務,但是你可能是對的:P – LukeHennerley 2013-02-11 16:41:03

+0

好的,謝謝你的想法。我會檢查他們。這是巨大的幫助 – user1750355 2013-02-11 17:02:22

7

其實FileSystemWatcher的稱爲由.NET本身單獨的線程。所以基本上你需要做的絕對沒有創建活動 。你的代碼是可以的。

這裏是證明:

class Program 
{ 
    static void Main(string[] args) 
    { 
     FileSystemWatcher fw = new FileSystemWatcher(@"C:\temp"); 
     fw.Created += fileSystemWatcher_Created; 

     Console.WriteLine(Thread.CurrentThread.ManagedThreadId); 

     fw.EnableRaisingEvents = true; 

     Console.ReadLine(); 
    } 

    static void fileSystemWatcher_Created(object sender, FileSystemEventArgs e) 
    { 
     Console.WriteLine(Thread.CurrentThread.ManagedThreadId); 
    } 
}