如何在 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】:检查事项...
waitHandle
是 AutoResetEvent
还是 ManualResetEvent
? (从你的使用方式来看,应该是AutoResetEvent
如果shouldStop
是true
,当Work()
退出时,FileWacherThread
(sic) 是否设置为null
...
您如何保护对FileWacherThread
的访问?如果它被多个线程访问(检查它的状态,分配等,那么它也应该被锁保护)。
当您设置事件时,您不必担心FileWacherThread
的状态。如果您想向该线程发出信号,只需设置它,(即构建您的多线程代码,使发布者不知道/关心订阅者的当前状态)。
目前有一些状态表明您的FileWacherThread
可以在它不等待的地方,但它可能仍需要发出信号。如果你总是设置事件,最糟糕的情况是它会不必要地循环一次。
【讨论】:
以上是关于如何在 C# 控制台应用程序的多线程中同时实现 FileSystemWatcher 和 Timer?的主要内容,如果未能解决你的问题,请参考以下文章