FileSystemWatcher在队列中丢失文件
本文关键字:文件 队列 FileSystemWatcher | 更新日期: 2023-09-27 18:04:23
我编写了一个FileSystemWatcher
,为每个文件调用一次pgm。但是我的一些文件丢了。我只用10-11个文件测试了代码。删除文件会被正确记录,但创建文件则不会。有些文件没有记录。在我的任务执行中是否有任何问题?或者Window Service
有问题吗?
public static FileSystemWatcher m_Watcher;
static BlockingCollection<string> blockingCollection = new BlockingCollection<string>();
protected override void OnStart(string[] args)
{
current_directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
//XmlDocument xml = new XmlDocument();
try
{
strDir = ConfigurationManager.AppSettings["Directory"];
fileMask = ConfigurationManager.AppSettings["FileMask"];
strBatfile = ConfigurationManager.AppSettings["Batch"];
strlog = ConfigurationManager.AppSettings["Log"];
m_Watcher = new FileSystemWatcher();
m_Watcher.Filter = fileMask;
m_Watcher.Path = strDir + "''";
m_Watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
m_Watcher.Created += new FileSystemEventHandler(OnCreated);
m_Watcher.Deleted += new FileSystemEventHandler(OnDeleated);
m_Watcher.Renamed += new RenamedEventHandler(OnRenamed);
m_Watcher.EnableRaisingEvents = true;
}
catch (Exception exception)
{
CustomException.Write(CustomException.CreateExceptionString(exception.ToString()));
}
}
public static void OnDeleated(object source, FileSystemEventArgs e)
{
try
{
Log.getLogger("File deleated- Filename :" + e.Name + " at timestamp : " + DateTime.Now.ToString(), strlog);
}
catch (Exception exception)
{
CustomException.Write(CustomException.CreateExceptionString(exception, e.Name));
}
}
private static void OnCreated(object source, FileSystemEventArgs e)
{
var exceptions = new ConcurrentQueue<Exception>();
try
{
Task.Factory.StartNew(() =>
{
try
{
blockingCollection.Add(e.Name.ToString());
}
catch (Exception)
{
throw;
}
});
Task.Factory.StartNew(() =>
{
try
{
foreach (string value in blockingCollection.GetConsumingEnumerable())
{
System.Diagnostics.Process.Start(Service1.strBatfile);
Log.getLogger("File Processed after executing batch: Filename ->:" + value + " " + "Batch File Executed- > " + Service1.strBatfile + " at timestamp : " + DateTime.Now.ToString(), Service1.strlog);
}
}
catch (Exception)
{
throw;
}
});
}
catch (AggregateException ae)
{
foreach (var ex in ae.InnerExceptions)
{
CustomException.Write(CustomException.CreateExceptionString(ex, e.Name));
}
}
finally
{
m_Watcher.EnableRaisingEvents = true;
}
}
你正在使用许多线程/任务来清楚地理解代码是如何工作的。正如您所述,您希望一次只处理一个文件,您只需要一个线程/任务,该线程/任务在类(我假设是应用程序)的生命周期内存在。
如果我剥离你的代码,每次完成一个文件的处理,每当一个文件被放入某个文件夹时,这可能是一个实现。
注意我如何有一个ConcurrentQueue
和一个方法读取队列。我还在流程实例上使用WaitForExit
方法,以防止运行多个进程。
static ConcurrentQueue<string> filenames = new ConcurrentQueue<string>();
static void QueueHandler()
{
bool run = true;
AppDomain.CurrentDomain.DomainUnload += (s, e) =>
{
run = false;
filenames.Enqueue("stop");
};
while(run)
{
string filename;
if (filenames.TryDequeue(out filename) && run)
{
var proc = new Process();
proc.StartInfo.FileName = filename;
proc.Start();
proc.WaitForExit(); // this blocks until the process ends....
}
}
}
现在我们需要一个单独的任务/线程来运行QueueHandler
和FileSystemWatcher
:
protected override void OnStart(string[] args)
{
// have our queue reader method started
Task.Factory.StartNew(QueueHandler);
var fsw = new FileSystemWatcher();
fsw.Created += (o, e) =>
{
// add a file to the queue
filenames.Enqueue(e.FullPath);
// optionally add polling for missed files
// http://stackoverflow.com/questions/239988/filesystemwatcher-vs-polling-to-watch-for-file-changes
};
fsw.Path = ConfigurationManager.AppSettings["Directory"];
fsw.NotifyFilter = NotifyFilters.FileName;
fsw.Filter = ConfigurationManager.AppSettings["FileMask"];
fsw.EnableRaisingEvents = true;
}
这个实现将在最坏的情况下使用三个线程:一个主线程,一个用于FileSystemWatcher
的创建事件,一个用于QueueHandler
,如果您的示例代码中每次在文件夹中创建新文件时都启动新的任务,FileSystemWatcher正在监视
在OnCreated
方法中启动两个任务,其中第二个任务似乎依赖于第一个任务的输出。但是,不能保证第一个任务在第二个任务执行时已经完成(甚至已经启动)。
您可以将这两个操作分组到一个任务中,然后依次执行,或者您可以将第一个任务的结果await
。
你的代码中也有很多信息丢失了。这显然不是"真正的"代码,因为OnDeleated
[原文如此]拼写错误,无法编译。我们也无法看到您的外部进程是什么,或者您是如何试图将文件列表传递给它的。那里可能会有很多问题。是否有可能张贴实际代码?