Как реализовать FileSystemWatcher и Timer в многопоточности в консольном приложении C #? - PullRequest
0 голосов
/ 04 октября 2011

Мне нужно создать консольное приложение C #, которое будет анализировать файл из каталога SFTP при создании нового файла. Для этого я реализовал FileSystemWatcher с событием FileCreated, которое ставит в очередь новый путь к файлу, создает новый поток и анализирует файл.

Я читал в блогах, что иногда FileSystemWatcher может не обнаруживать новые файлы, для этого я реализовал Timer, который будет запускаться каждые 1 час, и если поток FileSystemWatcher находится в состоянии ожидания, то будет читать папку IMCOMING SFTP и анализировать файл ,

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

MAIN

   static void Main(string[] args)
    {
        try
        {                
            string path = incomingFilePath;
            if (Directory.Exists(path))
            {
                #region Initiate Timer
                Thread t = new Thread(new ParameterizedThreadStart(ThreadLoop));                    
                t.Start((Action)fileProcessor.StartTimer);
                #endregion

                #region FileSystemWatcher
                watcher = new FileSystemWatcher { Path = path, Filter = "*.CUST", IncludeSubdirectories = true };
                watcher.Created += new
                FileSystemEventHandler(watcher_FileCreated);
                watcher.Error += new
                ErrorEventHandler(watcher_OnError);
                watcher.EnableRaisingEvents = true;
                #endregion
            }
        }
        catch (Exception Err)
        {

        }
    }

КОД FILESYSTEMWATCHER:

 private static void watcher_FileCreated(object sender, FileSystemEventArgs e)
  {
        if (e.FullPath.ToUpper().Contains("INCOMING"].ToString()))
        {                               
            fileProcessor.EnqueueFile(e.FullPath);
            lock (lockObject)
             {
               files.Enqueue(path);
             }

            if (FileWacherThread == null || shouldStop)
            {
               FileWacherThread = new Thread(new ThreadStart(Work));                
              FileWacherThread.Start();
            }
           // If the thread is waiting then start it
           else if (FileWacherThread.ThreadState == ThreadState.WaitSleepJoin)
           {               
              waitHandle.Set();
           }
        }
    }

  private void Work()
    {
        while (!shouldStop)
        {
            string path = String.Empty;
            lock (lockObject)
            {
                if (files.Count > 0)
                {
                    path = files.Dequeue();
                }
            }

            if (!String.IsNullOrEmpty(path))
            {
                // Process the file                    
                ParseFile(path);
            }
            else
            {
                // If no files are left to process then wait
                waitHandle.WaitOne();
            }
        }
    }

КОД ТАЙМЕРА

 public void StartTimer()
    {
        lock (lockObject)
        {
           if (FileWacherThread == null || FileWacherThread.ThreadState == ThreadState.WaitSleepJoin)
            {
                if (files.Count == 0)
                {
                    IEnumerable<string> result = new List<string>(Directory.GetFiles(incomingFilePath, "*.CUST", SearchOption.AllDirectories)).Where(s => s.Contains(incomingFilePrefix));
                    foreach (string path in result)
                    {
                        ParseFile(path);
                    }
                }
            }
        }
     }

1 Ответ

0 голосов
/ 14 октября 2011

Что проверить ...

это waitHandle AutoResetEvent или ManualResetEvent? (от того, как вы его используете, это должно быть AutoResetEvent

Если shouldStop равно true, FileWacherThread (sic) установлено в null, когда Work() выходит ...

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

Вам не нужно беспокоиться о состоянии FileWacherThread, когда вы устанавливаете событие. Если вы хотите дать сигнал этому потоку, просто установите его (т.е. создайте свой многопоточный код так, чтобы издатель не знал / не заботился о текущем состоянии подписчика). В настоящее время есть состояния, что ваш FileWacherThread может находиться там, где он не ждет, но, возможно, ему все равно нужно будет сигнализировать. Если вы всегда устанавливаете событие, самое худшее, что может произойти, это то, что оно зацикливается один раз без необходимости.

...