2016-06-16 3 views
0

fileSystemWatcher를 사용하여 새 파일에 대해 매핑 된 네트워크 경로를 모니터링하는 콘솔 응용 프로그램이 있습니다. 파일이 나타나면 파일의 내용에 따라 파일의 이름이 바뀝니다. 나는 이것을 24/7 달리기를 원한다. 그것은 한동안 잘 작동하지만 잠시 후 콘솔이 "일시 중지"되고 입력을 기다리고있는 것 같습니다. 콘솔에서 리턴 값을 얻으면, 애플리케이션은 어떤 유형의 입력을 기다리는 "보류 중"상태였던 모든 이벤트를 따라 잡는 것처럼 보입니다. 일시 중지되거나 이유가있는 코드에서이 문제를 재현하는 것처럼 보이지 않습니다.콘솔 응용 프로그램 "일시 중지"C#

외부 요인 (서버 재시작, 네트워크 문제 등)으로 인해 네트워크 경로를 모니터링 할 수있는 파일 시스템 감시자와 관련이 있다고 가정 했으므로 파일 시스템 감시자를 30 분 동안 다시 만들었습니다. 나는 지금 실제로 그 상황과 관련이 없다고 확신한다.

본질적으로 콘솔은 행복하게 발견 된 새 파일에 대한 업데이트를 인쇄하고 있지만 그냥 멈추고 (출력뿐 아니라 프로그램 작업도) 멈추지 않을 것이며 계속되지 않을 것입니다. 콘솔 앱에 포커스를두고 키를 누르기 전까지 타이머 대기 시간과 파일 시스템 감시자 재 작성과 같은 보류중인 모든 이벤트가 발생합니다.

질문 : 이것은 왜 발생하며 어떻게 방지합니까?

너트 및 프로그램의 볼트는 다음과 같습니다

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

아니요.이 동작이 발생하기 전에 가끔씩 실행됩니다. 아무도 할 수 없습니다. – rune711

답변

0

가 (스콧이 말한 것처럼) 사용 A를 합니다 (GetInput()에서 GetInput()를 호출하여 발생할 수 있음)에 유래 예외를 제거하려면 재귀 적 메서드 호출 대신 루프.

FileSystemWatcher를 다시 만들 필요가 없습니다. 아직 파일을 작성하지 않았기 때문에 파일을 읽는 동안 예외가 발생합니다.

재귀 메소드 호출 대신 while 루프를 사용하는 방법 : 예외 ocurs, 당신은 그것을 시도하지 않을 때 FileSystemWatcher 구성 이벤트에

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(); 
    } 
} 

문제가있다. List<string>에 파일 이름을 추가하고 파일을 구문 분석하려고하는 타이머를 만들 수 있습니다. 성공하면 목록에서 제거 할 수 있습니다. 이 명령은 runAll 명령으로 수행 할 수 있습니다. 직접 파일을 구문 분석하는 대신 모든 파일을 목록에 추가 할 수 있습니다.

+0

미안하지만이 질문에 대한 대답이라고 생각하지 않는다. @Scott은 확실히 자신의 조언에 맞다. . FileSystemWatcher 이벤트가 발생하는 방식으로 인해 파일 쓰기가 완료되지 않은 경우에도 일부 파일 잠금 검사 및 오류 처리를 수행하는 parseTheFile()에 논리를 통합했습니다. 그러나 이벤트에서 오류가 발생하더라도 내가 보는 행동을 설명하지는 않습니다. – rune711

0

아! 나는 어떤 일이 일어 났는지 생각해 본다. 그리고 분명히 다른 사람들이이 권리를 보았을 것이기 때문에 전체 프로그램이 여기에 게시되지 않았다는 점에 유감스럽게 생각한다. @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"이벤트를 기다리는 동안 "일시 중지"됩니까? 나는 이것을 고쳤고 지난 밤에 도망 쳤고 모든 것이 오늘 아침에도 잘 풀려서 문제가 다시 보일 때 나는 다시 올 것이다. 그러나 나는 이것이 그 것이라고 확신한다.