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

Posted

技术标签:

【中文标题】如何在 C# 控制台应用程序的多线程中同时实现 FileSystemWatcher 和 Timer?【英文标题】:How to implement both the FileSystemWatcher and Timer in Multithreading in C# console application? 【发布时间】:2011-11-30 18:08:31 【问题描述】:

我需要创建一个 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);
                    
                
            
        
     

【问题讨论】:

什么实际上不起作用? 顺便说一句,如果您的客户文件很大,您的计时器代码可能还会找到仍在写入的文件,除非您首先创建了一个临时文件并在完成后将其重命名为 *.CUST。 . 【参考方案1】:

检查事项...

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

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

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

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

【讨论】:

以上是关于如何在 C# 控制台应用程序的多线程中同时实现 FileSystemWatcher 和 Timer?的主要内容,如果未能解决你的问题,请参考以下文章

如何实现令牌系统以限制 C# 中处理器/IO 繁重的多线程任务的并发性?

C#爬虫爬虫的多线程如何实现

C#中的多线程

为啥 C# 中的多线程不能达到 100% CPU?

如何实现springMVC的多线程并发?

如何实现springMVC的多线程并发?