2013-02-11 16 views
10

私は選択したフォルダに* .logファイルをリッスンするアプリケーションを持っています。私はFileSystemWatcherを使用しました。File.Existsまで待つ方法

しかし、問題があります。

  1. が適切なものにtxtファイル(いくつかのランダムなファイル名)
  2. 変更に* .txtの名前を、それを解凍します* .gzをファイルを作成します。そのファイルを作るための責任を他のアプリでは、手順に従って取り* .log拡張子付き。

この動作は変更できません。

したがって、* .gzファイルと* .txtファイルには2 FileSystemWatcherが作成されました。どうして?このアプリケーションはgzファイルを解凍しないことがあり、txtファイルの名前を最終的な* .logファイルに変更しないことがあります。

FileSystemWatcher2キャッチtxtファイル(ほとんどの場合、次の1000msでログに名前が変更されます)txtファイルが存在するかどうかを確認するまでに時間がかかることがあります(そうでない場合は、 .logファイル)。

質問は、UIがフリーズしないようにThread.Sleep()なしでファイルが存在するかどうかを確認する方法です。

私はそれが明確ではないかと思いますが、私はそれをより良く記述しようとします。私はこれが複雑な問題だと思う。

いくつかのサンプルコード:

ウォッチャー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()'んです放棄THEスレッド、彼らは他のタスクに使用することができるように、それが使用しているコンピュータのリソースを解放:ここ

は証拠です。いくつかのシナリオでは理想的ではありません(1ミリ秒の最小単位があるため)が、達成しようとしているものについてはうまくいくかもしれません。 –

+0

@RobertHarveyこれについてのドキュメントがありますか?私の経験から、Thread.Sleepは、時間が経過するまでスレッドがそれ以上の命令を処理しないようにします。 MSDNから: 'スレッドは、指定された時間、オペレーティングシステムによって実行のためにスケジュールされません。 ' – CodingGorilla

+0

@CodingGorilla:はい、そうです。スレッドは他のタスクのために保持しているリソースをブロックし、解放します。基本的には「次のnミリ秒間は何もしないので、その間に別のことをすることができます」と言っています。 –

答えて

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

+0

@コーディングゴリラ明らかに、これはタスク用のOPフレームワークに依存するでしょうが、おそらく正しいでしょう:P – LukeHennerley

+0

OK、アイデアをありがとう。私はそれらを確認します。それはメガに役立つ – user1750355

3

あなたは、ファイルシステムを監視するためにBackGroundWorkerを使用することができます - そして、あなたのUIの凍結を避ける

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); 
    } 
} 
関連する問題