如何在C#控制台应用程序中实现多线程中的FileSystemWatcher和Timer?

时间:2011-10-04 14:24:37

标签: c# multithreading timer console-application filesystemwatcher

我需要创建一个C#控制台应用程序,它将在创建新文件时从SFTP目录解析文件。为此,我使用FileCreated事件实现了FileSystemWatcher,该事件将新文件路径排入队列并创建新线程并解析文件。

我在博客中读到有些时候FileSystemWatcher可能无法检测到新文件,因为我实现了Timer,它将每1小时触发一次,如果FileSystemWatcher线程处于等待状态,那么将读取IMCOMING SFTP文件夹并解析文件。

下面是我为FileSystemWatcher和Timer编写的代码,但它无法正常工作,我认为filesystemwatcher不在多线程中。请帮我解决问题。

主要

   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 :(得分:0)

要检查的事情......

waitHandle AutoResetEvent还是ManualResetEvent? (从您使用它的方式来看,它应该是AutoResetEvent

如果shouldStoptrueFileWacherThread(sic)在null退出时设为Work() ...

您如何保护对FileWacherThread的访问权限?如果从多个线程访问它(检查其状态,分配等,那么它也应该用锁保护)。

设置事件时,您不必担心FileWacherThread的状态。如果你想发信号给那个线程,只需设置它,(即构建你的多线程代码,使发布者不知道/关心订阅者的当前状态)。 目前,有些州表示您的FileWacherThread可以处于不等待的位置,但可能仍需要发出信号。如果你总是设置事件,可能发生的最坏情况是它不必要地循环一次。