如何在c#控制台应用程序中实现多线程中的文件系统监视器和定时器

本文关键字:文件系统 监视器 定时器 多线程 实现 控制台 应用程序 | 更新日期: 2023-09-27 18:10:28

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

我在博客中读到,有时FileSystemWatcher可能无法检测到新文件,为此我实现了计时器,它将每1小时触发一次,如果FileSystemWatcher线程处于等待睡眠状态,那么将读取即将到来的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();
            }
        }
    }
<<p> 定时器代码/strong>
 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);
                    }
                }
            }
        }
     }

如何在c#控制台应用程序中实现多线程中的文件系统监视器和定时器

检查事项…

waitHandleAutoResetEvent还是ManualResetEvent ?(从你使用它的方式来看,它应该是一个AutoResetEvent

如果shouldStoptrue,当Work()退出时,FileWacherThread (sic)是否设置为null

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

当您设置事件时,不应该担心FileWacherThread的状态。如果你想向该线程发送信号,只需设置它(即构建多线程代码,使发布者不知道/关心订阅者的当前状态)。目前有状态,你的FileWacherThread可以在那里,它不等待,但它可能仍然需要被标记。如果总是设置事件,最坏的情况可能是它不必要地循环一次。