FileSystemWatcher触发后——使用线程池还是专用线程?

5
我即将实施典型的FileSystemWatcher解决方案。我有一个要监视文件创建的目录,并且需要将创建的文件读取并插入到数据库中。大致上,这将涉及到读取和处理6或7个80个字符的文本文件,这些文件以每几秒钟一次的突发速率150毫秒的速度出现,很少会有一个2MB的二进制文件也需要被处理。这可能是一个24/7的过程。
根据我所了解的FileSystemWatcher对象,最好将其事件排队在一个线程中,然后在另一个线程中出队/处理它们。我现在面临的问题是,哪种方法是更好的处理线程的创建机制。我能想到的选择如下:
1. 每次获取FSW事件时手动创建一个新线程(是的,我知道...愚蠢的架构,但我必须说一下)。 2. 每当我收到FSW事件时,将处理抛到CLR线程池中。 3. 在启动时,创建一个专用的第二个线程进行处理,并使用生产者/消费者模型来处理工作。主线程将请求排队,第二个线程将其出队并执行工作。
我倾向于第三种方法作为首选方法,因为我知道工作线程总是需要的,而且可能更加需要,因为我对线程池没有感觉。
3个回答

3
如果你知道第二个线程总是需要的,而且你也知道你永远不需要超过一个工作线程,那么选项三已经足够好了。

1
+1,我要补充的是,使用线程池将会尝试在多个线程上同时处理您的请求,这对您的应用程序来说似乎并不是一件好事。 - John Knoeller
根据我的测试,除了二进制文件处理外,我的处理应该在150毫秒内完成。二进制文件处理需要大约150毫秒,但这种情况应该很少发生,如果有排队等待的任务,也有足够的时间赶上进度。 - Peter M

3
第三个选项是最合理的。
关于FSW缺少一些文件事件,我实现了以下内容: 1)FSW对象在FileCreate上触发 2)tmrFileCheck,ticks = 5000(5秒) - 调用tmrFileChec_Tick
当FileCreate事件发生时,如果(tmrFileCheck.Enabled == false),则tmrFileCheck.Start()。
这样,在10秒后,tmrFileCheck_Tick会启动,其中 a) tmrFileCheck.Stop() b) CheckForStragglerFiles
在我运行的测试中,这对每分钟创建不到100个文件的情况下有效。
另一个变体是仅每隔NN秒拥有一个计时器滴答,并扫描散兵游勇的文件所在的目录(目录)。
另一个变体是雇佣我按F5刷新窗口并在有散兵游勇的文件时给您打电话;只是一个建议。 :-P

2
请注意,FileSystemWatcher 可能会错过事件,不能保证它会传递已发生的所有特定事件。通过将接收事件的线程执行的工作量最小化来设计,可以减少发生这种情况的可能性,但鉴于有限的事件缓冲区大小(最多为 64KB),仍有可能出现问题。
如果您决定使用 FileSystemWatcher,我强烈建议开发一系列的压力测试。
在我们的测试中,我们遇到了网络位置的问题,即使更改了 InternalBufferSize 也无法解决,但当我们遇到这种情况时,我们也没有收到错误事件通知。
因此,我们开发了自己的轮询机制,使用 Directory.GetFiles,然后将返回的文件状态与先前轮询的状态进行比较,确保我们始终具有准确的增量。
当然,这会带来相当大的性能成本,这可能对您来说不够好。

1
Leon,我非常清楚FSW的限制和问题。它在网络共享上似乎不够强大。我只会在本地目录中使用它,并且我不认为FSW事件缓冲区大小会给我带来问题。我正在计划一个清理程序以防万一我错过了一些东西。 - Peter M
Leon,顺便说一下,我将计划进行大量测试。FSW似乎有很多隐藏的陷阱。 - Peter M
如果我在做这件事,我会选择FSW,并定期(也许每天,在系统通常比较安静的时间)对目录进行全面扫描,以确保所有内容都被捕获。 - Anon.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接