2015-01-18 2 views
0

ОК, поэтому на этот раз я создал службу с наблюдателем файлов для обработки файла после его создания.Проблема с FileWatcher

кажется, что моя служба аварийно завершает работу, когда обрабатываемые файлы достигают 1000 (я получаю массу сообщений).

вот моя логика: файлы поступают, файлы просматривают текст, отправляют его по электронной почте, вставляют в БД, перемещают исходное сообщение в папки.

в начале службы, я обрабатываю ожидающие сообщения сначала, прежде чем начать смотреть (я говорю о более чем 1000 ожидающих текстового файла), а моей службе требуется около секунды для работы над каждым файлом.

Все идет нормально, но когда общее количество входящих файлов достигает 1000, оно просто падает. иногда служба прекращает обработку в ожидании и только начинает искать только новые файлы.

У меня есть «InternalBufferSize = 64000», рекомендованный максимум.

Пожалуйста, помогите мне с моим кодом (я знаю, что это должно быть многопоточных для лучшей управляемости, но я не тот эксперт):

protected override void OnStart(string[] args) 
    { 
     using(TREEEntities TEX = new TREEEntities()) 
     { 
     var mp= TEX.TREE_settings.FirstOrDefault(x=>x.SET_key =="MSGDump"); 
     MsgsPath = mp.SET_value; 
     var dc = TEX.TREE_settings.FirstOrDefault(x => x.SET_key == "DupCash"); 
     DupCash = Convert.ToInt16(dc.SET_value); 
     } 
     if (Directory.Exists(MsgsPath)) 
     { 
      if (!Directory.Exists(MsgsPath+"\\Archive")) 
      { 
       Directory.CreateDirectory(MsgsPath+"\\Archive"); 
      } 
      if (!Directory.Exists(MsgsPath + "\\Duplicates")) 
      { 
       Directory.CreateDirectory(MsgsPath + "\\Duplicates"); 
      } 
      if (!Directory.Exists(MsgsPath + "\\Unsent")) 
      { 
       Directory.CreateDirectory(MsgsPath + "\\Unsent"); 
      } 
     } 
     else 
     { 
      Directory.CreateDirectory(MsgsPath); 
      Directory.CreateDirectory(MsgsPath + "\\Archive"); 
      Directory.CreateDirectory(MsgsPath + "\\Duplicates"); 
      Directory.CreateDirectory(MsgsPath + "\\Unsent"); 
     }   

     processPending();//<--- process pending files after last service stop 
     fileSystemWatcher1.Path = MsgsPath;//<--- path to be watched 
     fileSystemWatcher1.EnableRaisingEvents = true; 
     fileSystemWatcher1.InternalBufferSize = 64000; 
     addToLog(DateTime.Now, "Service Started", 0, "Service", "Info"); 
     addToLog(DateTime.Now, "File Watcher Started", 0, "Service", "Info"); 
     //dupList.Clear();//<--- clear duplicates validation list 
    } 

    protected override void OnStop() 
    { 
     fileSystemWatcher1.EnableRaisingEvents = false; 
     addToLog(DateTime.Now, "File Watcher Stopped", 0, "Service", "Alert"); 
     addToLog(DateTime.Now, "Service Stopped", 0, "Service", "Alert"); 
    } 



    private void fileSystemWatcher1_Created(object sender, FileSystemEventArgs e) 
    {    
     try 
     { 
      //---------read from file------------ 
      Thread.Sleep(200);//<---give the file some time to get released 
      string block; 
      using (StreamReader sr = File.OpenText(MsgsPath + "\\" + e.Name)) 
      { 
       block = sr.ReadToEnd(); 
      } 
      PRT = block.Substring(block.Length - 6, 6);//<--- get the printer name 
      seq = Convert.ToInt16(block.Substring(block.Length - 20, 20).Substring(0, 4));//<--- get the sequence number 
      switch (PRT)//<----track sequence number from the 3 printers 
      { 
       case "64261B"://<---prt1 
        int seqPlus1=0; 
        if(seqPrt1 == 9999)//<---ignore sequence change from 9999 to 1 
        { seqPlus1 = 1; } 
        else { seqPlus1 = seqPrt1 + 1; }       
        if (seq != seqPlus1 && seqPrt1 != 0)//<---"0" to avoid first service start 
        { 
         int x = seq - seqPrt1 - 1; 
         for (int i = 1; i <= x; i++) 
         { 
          addToMissing(PRT, seqPlus1); 
          addToLog(DateTime.Now, "Missing Sequence Number On Printer: " + PRT + " - " + seqPlus1, seqPlus1, "Service", "Missing"); 
          seqPlus1++; 
         }       
         seqPrt1 = seq; 
        } 
        else { seqPrt1 = seq; } 
        break; 
       case "24E9AA"://<---prt2 
        int seqPlus2=0; 
        if(seqPrt2 == 9999) 
        { seqPlus2 = 1; } 
        if (seq != seqPlus2 && seqPrt2 != 0) 
        { 
         int x = seq - seqPrt2 - 1; 
         for (int i = 1; i <= x; i++) 
         { 
          addToMissing(PRT, seqPlus2); 
          addToLog(DateTime.Now, "Missing Sequence Number On Printer: " + PRT + " - " + seqPlus2, seqPlus2, "Service", "Missing"); 
          seqPlus2++; 
         }       
         seqPrt2 = seq; 
        } 
        else { seqPrt2 = seq; } 
        break; 
       case "642602"://<---prt3 
        int seqPlus3=0; 
        if(seqPrt3 == 9999) 
        { seqPlus3 = 1; } 
        if (seq != seqPlus3 && seqPrt3 != 0) 
        { 
         int x = seq - seqPrt3 - 1; 
         for (int i = 1; i <= x; i++) 
         { 
          addToMissing(PRT, seqPlus3); 
          addToLog(DateTime.Now, "Missing Sequence Number On Printer: " + PRT + " - " + seqPlus3, seqPlus3, "Service", "Missing"); 
          seqPlus3++; 
         }      
         seqPrt3 = seq; 
        } 
        else { seqPrt3 = seq; } 
        break; 
      } 
      block = block.Remove(block.Length - 52);//<--- trim the sequence number and unwanted info 
      string[] Alladd; 
      List<string> sent = new List<string>(); 
      if (!dupList.Contains(block)) //<--- if msg not found in duplicates validation list 
      { 
       //--------extract values-------------- 
       if (block.Substring(0, 3) == "\r\nQ") //<--- if the msg. contains a priority code 
       { 
        Alladd = block.Substring(0, block.IndexOf(".")).Replace("\r\n", " ").Substring(4).Split(' ').Distinct().Where(x => !string.IsNullOrEmpty(x)).ToArray(); ; 
       } 
       else//<--- if no priority code 
       { 
        Alladd = block.Substring(0, block.IndexOf(".")).Replace("\r\n", " ").Substring(1).Split(' ').Distinct().Where(x => !string.IsNullOrEmpty(x)).ToArray(); ; 
       } 
       string From = block.Substring(block.IndexOf('.') + 1).Substring(0, 7); 
       string Msg = block.Substring(block.IndexOf('.') + 1); 
       Msg = Msg.Substring(Msg.IndexOf('\n') + 1); 

       //--------add msg content to the DB group table-------- 
       using (TREEEntities TE1 = new TREEEntities()) 
       { 
        TREE_group tg = new TREE_group() 
        { 
         GROUP_original = block, 
         GROUP_sent = Msg, 
         GROUP_dateTime = DateTime.Now, 
         GROUP_from = From, 
         GROUP_seq = seq, 
         GROUP_prt = PRT, 
        }; 
        TE1.AddToTREE_group(tg); 
        TE1.SaveChanges(); 
        GID = tg.GROUP_ID; 
       } 
       //--------validate addresses--------------- 
       foreach (string TB in Alladd) 
       { 
        string email = ""; 
        string typeB = ""; 
        TREEEntities TE = new TREEEntities(); 
        var q1 = from x in TE.TREE_users where x.USR_TypeB == TB && x.USR_flag == "act" select new { x.USR_email, x.USR_TypeB }; 
        foreach (var itm in q1) 
        { 
         email = itm.USR_email; 
         typeB = itm.USR_TypeB; 
        } 

        //-------send mail if the user exist----     
        if (TB == typeB) 
        { 
         if (typeB == "BAHMVGF") 
         { 
          addToFtl(block); 
         } 
         try 
         { 
          sendMail SM = new sendMail(); 
          SM.SendMail(Msg, "Message from: " + From, email); 
          //---save record in DB---- 
          addToMsg(typeB, email,"sent","act",1,GID,seq);        
          sent.Add(typeB); 
         } 
         catch (Exception x) 
         { 
          addToMsg(typeB, email, "Failed", "act", 1, GID, seq);        
          addToLog(DateTime.Now, "Send message failed: " + x.Message, GID, "Service", "Warning"); 
         } 
        } 
        //-------if no user exist---- 
        else 
        { 
         if (TB == "BAHMVGF") 
         { 
          addToFtl(block); 
         } 
         addToMsg(TB, "No email", "Failed", "act", 1, GID, seq);       
         addToLog(DateTime.Now, "Send message failed, unknown Type-B address: " + TB, GID, "Service", "Warning"); 
        } 
       } 

       if (sent.Count < Alladd.Count())//<--- if there is unsent addresses 
       { 
        StringBuilder b = new StringBuilder(block); 
        foreach (string add in sent) 
        { 
         b.Replace(add, "");//<--- remove address that has been sent from the original message and write new msg. to unsent folder 
        } 
        if (!Directory.Exists(MsgsPath + "\\Unsent")) 
        { 
         Directory.CreateDirectory(MsgsPath + "\\Unsent"); 
        } 
        using (StreamWriter w = File.AppendText(MsgsPath + "\\Unsent\\" + e.Name)) 
        { 
         w.WriteLine(b); 
        } 
       } 
       sent.Clear(); 
       //---add to dupList to validate the next messages------------- 
       if (dupList.Count > DupCash) 
       { 
        dupList.RemoveAt(0); 
       } 
       dupList.Add(block); 
       //---move msg to archive folder-----------------  
       if (!Directory.Exists(MsgsPath + "\\Archive")) 
       { 
        Directory.CreateDirectory(MsgsPath + "\\Archive"); 
       } 
       File.Move(MsgsPath + "\\" + e.Name, MsgsPath + "\\Archive\\" + e.Name); 
      } 

      else //<--- if message is a duplicate 
      { 
       addToLog(DateTime.Now, "Duplicated message, message not sent", seq, "Service", "Info"); 
       //---move msg to duplicates folder----------------- 
       if (!Directory.Exists(MsgsPath + "\\Duplicates")) 
       { 
        Directory.CreateDirectory(MsgsPath + "\\Duplicates"); 
       } 
       File.Move(MsgsPath + "\\" + e.Name, MsgsPath + "\\Duplicates\\" + e.Name); 
      } 

     } 
     catch (Exception x) 
     { 
      addToLog(DateTime.Now, "Error: " + x.Message, seq, "Service", "Alert"); 
      if (!Directory.Exists(MsgsPath + "\\Unsent")) 
      { 
       Directory.CreateDirectory(MsgsPath + "\\Unsent"); 
      } 
      //---move msg to Unsent folder-----------------      
      File.Move(MsgsPath + "\\" + e.Name, MsgsPath + "\\Unsent\\" + e.Name); 
     } 

    } 
+1

http://stackoverflow.com/questions/10195317/ what-are-practice-limits-on-the-number-of-filesystemwatcher-instance-a-server –

+0

Помогло бы увеличить размер буфера? У меня есть все файлы локально (выделенный сервер), а не в общей сети. –

+0

Если вам нужна помощь, и вы считаете, что это не дубликат ранее заданных вопросов и ответов, вам нужно быть более конкретным, чем просто «сбой». –

ответ

0

Я хотел бы добавить это как комментарий, но он превысил допустимое количество символов здесь.

Первое, что я заметил в вашем коде, что вы делаете всю обработку файлов внутри обработчика созданного события. Это не очень хорошая практика, вы всегда должны позволять обработчикам событий FileSystemWatcher выполнять минимальную работу, так как это может привести к переполнению, вероятно, к тому, с чем вы столкнулись. Вместо этого лучше делегировать работу отдельного потока. Вы можете добавить события в очередь и позволить фоновой теме беспокоиться об их использовании. Вы можете фильтровать файлы в обработчике событий, чтобы ваша очередь не заполнялась мусором.

Использование сна внутри обработчика событий также считается плохой практикой, поскольку вы будете блокировать событие FileSystemWatcher.

Максимальный размер буфера составляет 64 КБ, это не рекомендуемый размер буфера, если вы не имеете дело с длинными путями. Увеличение размера буфера является дорогостоящим, поскольку оно исходит из незагруженной памяти, которая не может быть заменена на диск, поэтому держите буфер как можно меньше. Чтобы избежать переполнения буфера, используйте свойства NotifyFilter и IncludeSubdirectories, чтобы отфильтровать уведомления об нежелательных изменениях.

И, наконец, я хотел бы предложить чтение FileSystemWatcher MSDN article и глядя на нескольких примерах в Интернете, прежде чем пытаться писать код как наблюдатель Windows, несколько деликатной и склонной к ошибкам

+1

Вы можете разделить на несколько комментариев. – tbodt

+0

@tbodt не нужно быть мудрым парнем, ответ действительно. Я бы посоветовал вам также прочитать статью MSDN. –

Смежные вопросы