我正在开发一个c#程序,它使用FilesystemWatcher来监视添加到monitor_directory中的PDF文件。每次将文件添加到目录时,我都会将其添加到另一个线程无限循环中连续弹出的BlockingQueue,它会等待添加文件路径,之后我继续处理文件,最后一部分PDF文件处理正在将其移动到输出目录。
调度线程:
private static void ThreadProc(object param)
{
FileMonitorManager _this = (FileMonitorManager)param;
FileProcessingManager processingManager = new FileProcessingManager();
processingManager.RegisterProcessor(new ExcelFileProcessor());
processingManager.RegisterProcessor(new PdfFileProcessor());
while (true)
{
try
{
var path = (string)_this.FileQueue.Dequeue();
if (path == null)
break;
bool b = processingManager.Process(path);
if (!b)
{
_this.FileQueue.Enqueue(path);
Console.WriteLine("\n\nError on file: " + path);
}
else
Console.WriteLine("\n\nSucces on file: " + path);
}
catch (System.Exception e)
{
Console.WriteLine(e.Message);
}
}
}
Process函数测试文件是否存在,进行一些处理并将PDF文件移动到输出目录。
我遇到了两个问题: 1.来自FileSystemWatcher的On_Create事件处理程序被触发TWICE,因此BlockingQueue具有相同的条目两次,在这种情况下,在处理例程中我验证文件是否尚未移动到输出目录(因为这是最后一部分)处理包括在那里移动文件),如果是这样我继续进行处理,如果没有我退出。 2.如果由于某种原因我在访问文件内容时遇到错误:该文件正由另一个进程使用我从Process函数返回FALSE并再次将文件路径添加到队列中。
现在......这有效,但它的工作有点慢..我怎么能通过考虑我面临的两个问题来做这个多线程.. 修改 如果我得到事件,将它添加到队列,它被弹出,队列为空,然后我再次得到相同的事件,队列是空的,所以它被添加了,基本上我得到同样的事件处理TWICE怎么办? / p>
答案 0 :(得分:3)
FileSystemWatcher非常讨厌。
我认为这就是我要做的......
执行此多线程的一种简单方法是每次出列路径时都启动一个新任务...
Task.Factory.StartNew(() =>
{
try
{
var path = (string) _this.FileQueue.Dequeue();
if (path == null)
break;
bool b = processingManager.Process(path);
if (!b)
{
_this.FileQueue.Enqueue(path);
Console.WriteLine("\n\nError on file: " + path);
}
else
Console.WriteLine("\n\nSucces on file: " + path);
}
catch (System.Exception e)
{
Console.WriteLine(e.Message);
}
});
对于生产代码,您还需要将取消令牌传递给任务,并具有停止循环和任务的机制。
答案 1 :(得分:0)
1) FileSystemWatcher 会两次通知您,因为文件分两步更新:首先是数据,然后是元数据。因此,您可以使用以下内容检查最新的写入是否已被考虑在内:
File.GetLastWriteTime(file);
或者您可以检查重复项。
2)你没有使用多线程:你一次处理一个文件,所以你可以产生一些线程来执行Process方法,例如:使用方法:
ThreadPool.QueueUserWorkItem