如何在C#控制台应用程序中实现多线程中的FileSystemWatcher和Timer?
我需要创建一个C#控制台应用程序,在创建新文件时,该应用程序将解析SFTP目录中的文件。为此,我使用FileCreated事件实现了FileSystemWatcher,该事件将新文件路径排队,并创建一个新线程并解析文件 我在博客中读到,FileSystemWatcher有时可能无法检测到新文件,因为我实现了计时器,它将每1小时启动一次,如果FileSystemWatcher线程处于waitsleep状态,则将读取IMCOMING SFTP文件夹并解析该文件 下面是我为FileSystemWatcher和Timer编写的代码,但它工作不正常,我认为FileSystemWatcher不支持多线程。请帮我找到正确的解决方案 MAIN如何在C#控制台应用程序中实现多线程中的FileSystemWatcher和Timer?,c#,multithreading,timer,console-application,filesystemwatcher,C#,Multithreading,Timer,Console Application,Filesystemwatcher,我需要创建一个C#控制台应用程序,在创建新文件时,该应用程序将解析SFTP目录中的文件。为此,我使用FileCreated事件实现了FileSystemWatcher,该事件将新文件路径排队,并创建一个新线程并解析文件 我在博客中读到,FileSystemWatcher有时可能无法检测到新文件,因为我实现了计时器,它将每1小时启动一次,如果FileSystemWatcher线程处于waitsleep状态,则将读取IMCOMING SFTP文件夹并解析该文件 下面是我为FileSystemWatc
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)
{
}
}
文件系统监视程序代码:
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);
}
}
}
}
}
public void StartTimer()
{
锁定(锁定对象)
{
if(FileWacherThread==null | | FileWacherThread.ThreadState==ThreadState.WaitSleepJoin)
{
如果(files.Count==0)
{
IEnumerable结果=新列表(Directory.GetFiles(incomingFilePath,“*.CUST”,SearchOption.AllDirectories)),其中(s=>s.Contains(incomingFilePrefix));
foreach(结果中的字符串路径)
{
解析文件(路径);
}
}
}
}
}
要检查的内容
waitHandle
是AutoResetEvent
还是ManualResetEvent
?(从您使用它的方式来看,它应该是一个AutoResetEvent
如果shouldStop
为true
,则文件wacherThread
(原文如此)是否在工作()退出时设置为null
如何保护对FileWacherThread
的访问?如果它是从多个线程访问的(为了检查其状态、分配等,那么它也应该使用锁进行保护)
设置事件时,您不必担心FileWacherThread
的状态。如果要向该线程发送信号,只需设置它(即,构建多线程代码,使发布者不知道/不关心订阅服务器的当前状态)。
目前有一些状态表明,您的FileWacherThread
可能处于未等待但可能仍需要发出信号的位置。如果您总是设置事件,最糟糕的情况可能是它不必要地循环一次。什么实际不起作用?顺便说一句,如果您的客户文件很大,您的计时器代码可能也会发现f仍在写入的文件,除非先创建临时文件,并在完成后将其重命名为*.CUST。。