2016-06-16 10 views
0

私はfileSystemWatcherを使って新しいファイルのマップされたネットワークパスを監視するコンソールアプリケーションを持っています。ファイルが表示されると、ファイルの内容に基づいて名前が変更されます。私はこれを24時間365日実行します。それは一度はうまく動作しますが、しばらくするとコンソールが "一時停止"し、入力を待っているように見えます。コンソールでリターンすると、アプリケーションはあるタイプの入力を待っている "保留中"だったすべてのイベントに追いついているようです。私はこの問題を再現して一時停止しているコードやその理由をコード内で捕まえることはできません。コンソールアプリケーション "pausing" c#

これは、ファイルシステムウォッチャーが外部要因(サーバーの再起動、ネットワークの問題など)によってネットワークパスを監視できなくなっていると想定していましたので、ファイルシステムウォッチャーを30分再作成します。私は実際には今の状況とはまったく関係がないと確信しています。

私が見ているのは、コンソールが見つけた新しいファイルの更新を喜んで印刷していることですが、それだけで停止します(出力だけでなくプログラムの操作)コンソールアプリケーションにフォーカスを当ててキーを押すまで(タイマーの経過やファイルシステムウォッチャーの再作成など)すべてのイベントが発生します。

質問は次のとおりです:なぜこれが起こっているのですか?それをどうやって防ぐのですか?プログラムのナットとボルトは次のようになります

:(GetInput()GetInput()を呼び出すことによって引き起こす可能性がある)StackOverflowの例外を取り除くために

static void Main(string[] args) 
{ 

    RefreshTimer = new Timer(1800000); //30 minutes 
    RefreshTimer.Elapsed += RefreshTimer_Elapsed; 
    RefreshTimer.Enabled = true; 
    writeHelp(); 
    reCreateWatcher(); 

    getInput(); 

} 


private static void writeHelp() 
{ 
    Console.WriteLine("HELP:"); 

    Console.WriteLine(@""); 
    Console.WriteLine("RENAMES FILES THAT ARE PLACED INTO THE WORKING FOLDER."); 

    Console.WriteLine("*************_Commands:_************"); 
    Console.WriteLine("'runAll' = will run the program on all files curently existing in the folder. Note that if a file has already been renamed the program SHOULD attempt the rename, find the file has already been renamed, and move to the next file."); 
    Console.WriteLine("'quit' = exits program"); 
    Console.WriteLine("'help' = shows this spiffy information."); 
    Console.WriteLine("[end]"); 
    Console.WriteLine(""); 


} 

private static void getInput() 
{ 
    Console.Write("Cmd ->"); 
    string k = Console.ReadLine(); 
    switch (k) 
    { 
     case "help": 
      writeHelp(); 
      break; 
     case "runAll": 
      string[] allFiles = System.IO.Directory.GetFiles(PATH_TO_FILES); 
      foreach (string curr in allFiles) 
      { 
       parseTheFile(curr); 
      } 
      break; 
     case "quit": 
      return; 
     default: 
      Console.WriteLine("Huh? Unknown command!"); 
      break; 
    } 

    getInput(); 
} 

private static void reCreateWatcher() 
{ 

    Console.WriteLine("re-starting watcher..."); 
    Console.WriteLine("Starting Monitor of: " + PATH_TO_FILES); 
    if (TheWatcher != null) 
    { 
     TheWatcher.Dispose(); 
    } 
    deleteOldFiles(); 
    try 
    { 
     TheWatcher = new FileSystemWatcher(PATH_TO_FILES, "*.pdf"); 
    } 
    catch (Exception ex) 
    { 

     Console.WriteLine("AN ERROR OCCURED WHEN TRYING TO SET UP THE FILE SYSTEM WATCHER ON, '" + PATH_TO_FILES + "'. THE ERROR WAS: " + ex.Message); 
     Console.WriteLine("Hit any key to exit."); 
     Console.ReadKey(); 
     Environment.Exit(0); 

    } 

    TheWatcher.NotifyFilter = NotifyFilters.LastWrite; 
    TheWatcher.Changed += theWatcher_Changed; 
    TheWatcher.EnableRaisingEvents = true; 
} 
static void theWatcher_Changed(object sender, FileSystemEventArgs e) 
{ 
    Console.WriteLine("New file found: " + e.Name); 
    parseTheFile(e.FullPath); 

} 
+1

コンソールでマウスを使用してテキストを選択した可能性はありますか? – recursive

+3

あなたは 'getInput()'で無限に再帰的なプログラムを持っています。あなたが幸運を得ず、コンパイラが末尾再帰を行わないようにした場合、最終的にStackOverflowを取得します。代わりに 'while(true)'ループを使用してください。 –

+0

いいえ、これは、この現象が起こる前に、時には1日ほど実行され、誰もそれを行うことができません。 – rune711

答えて

0

(スコットが言ったように)使用A whileループは再帰的メソッド呼び出しではなくループです。

FileSystemWatcherを再作成する必要はありません。まだファイルを書き込もうとしていないので、ファイルを読み込もうとしているときに例外が発生するでしょう。

代わりに、再帰的なメソッド呼び出しのwhileループを使用する例:

class Program 
{ 
    private static readonly string PATH_TO_FILES = @"d:\temp"; 

    static void Main(string[] args) 
    { 
     using (var watcher = new FileSystemWatcher(PATH_TO_FILES, "*.pdf")) 
     { 
      watcher.Changed += Watcher_Changed; 

      WriteHelp(); 

      while (true) 
      { 
       Console.Write("Cmd ->"); 
       string k = Console.ReadLine(); 
       switch (k) 
       { 
        case "help": 
         WriteHelp(); 
         break; 

        case "runAll": 
         string[] allFiles = System.IO.Directory.GetFiles(PATH_TO_FILES); 
         foreach (string curr in allFiles) 
         { 
          parseTheFile(curr); 
         } 
         break; 

        case "quit": 
         return; 

        default: 
         Console.WriteLine("Huh? Unknown command!"); 
         break; 
       } 
      } 


     } 
    } 

    private static void WriteHelp() 
    { 
     Console.WriteLine("HELP:"); 

     Console.WriteLine(@""); 
     Console.WriteLine("RENAMES FILES THAT ARE PLACED INTO THE WORKING FOLDER."); 

     Console.WriteLine("*************_Commands:_************"); 
     Console.WriteLine("'runAll' = will run the program on all files curently existing in the folder. Note that if a file has already been renamed the program SHOULD attempt the rename, find the file has already been renamed, and move to the next file."); 
     Console.WriteLine("'quit' = exits program"); 
     Console.WriteLine("'help' = shows this spiffy information."); 
     Console.WriteLine("[end]"); 
     Console.WriteLine(""); 


    } 

    private static void Watcher_Changed(object sender, FileSystemEventArgs e) 
    { 
     try 
     { 
      Console.WriteLine("New file found: " + e.Name); 
      parseTheFile(e.FullPath); 
     } 
     catch(Exception exception) 
     { 
      Console.WriteLine("Exception: " + exception.Message); 
     } 
    } 

    private static void parseTheFile(string fullPath) 
    { 
     throw new NotImplementedException(); 
    } 
} 

問題は、FileSystemWatcherイベント例外ocursに、あなたはそれを再試行することはありませんとき、です。 List<string>にファイル名を追加し、ファイルを解析しようとするタイマーを作成します。成功した場合はリストから削除できます。これはコマンドrunAllで行うことができます。直接ファイルを解析する代わりに、すべてのファイルをリストに追加することができます。

+0

申し訳ありませんが、これは質問に対する答えとは思われませんが、@Scottは間違いなく(真) 。 FileSystemWatcherイベントが発生する方法のため、ファイルの書き込みが完了していない場合でも、ファイルロックのチェックとエラー処理を行うparseTheFile()にロジックを組み込みました。しかし、イベントでエラーが投げられたとしても、私が見ている動作を説明するとは思わない。 – rune711

0

Ah!私は何が起こったのかを見ていると思うし、他の人がこの権利を確かに見たので確かにプログラム全体がここに掲載されていないのは残念だ。 @Scott Chamberlainが指摘するように、getInput()メソッドには再帰がありました。しかし、私はまた)parseTheFile内()もか、getInput(への呼び出しが含まれていることを指摘のようにいくつかのケースに応じて:私は明らかにイベント、静的メソッド、およびコンソールアプリケーションについて学ぶためにいくつかのものを持っている

static private void parseTheFile(string thePath) 
{ 
    Console.WriteLine("Attempting to parse " + System.IO.Path.GetFileName(thePath)); 
    string fileText; 
    try 
    { 
     fileText = GetTextFromPdf(thePath); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine("An error was encountered when trying to parse the file. " + ex.Message); 
     getInput(); // <---- WHOOPS! 
     return; 
     }... 

。本質的に私が起こっていることは、プログラムが始まり、文字列k = Console.ReadLine();で待っているgetInput()に行きます。ただし、イベントは新しいファイルを作成し、イベント内のgetInput()を別の呼び出しで呼び出すことがあります。。そのイベントは、私がリターンを打ち抜くまでは完了できません。さらに、@ Jeroenが指摘したように、fileSystemWatcherを再作成するときに、そのイベントの登録を抹消しませんでした。これは、私がリターンを打つと、他のすべてのイベントのカスケード効果がなぜ生じるのかを説明しています。どういうわけかコンソールは、これらのイベント内のこれらの "ReadLines"すべてを待っている "一時停止"ですか?私はこれを修正して昨晩行ったが、今朝もまだよく眠っているので、もう一度問題が見えたらもう一度投稿するだろうが、これは本当に確実だと思う。

関連する問題