2010-11-03 89 views
2

这有点复杂,但我会尽可能地尽力解释。等待FileSystemWatcher事件在完成线程之前触发

我使用的FileSystemWatcher的与

toFileWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.FileName; 

一个通知过滤器我有一个.Created方法和.Changed方法。

当.Created事件触发时,它会使用观察器提供的文件名进行一些初步检查,检查是否已经看到文件,获取目标文件夹并返回验证信息。

我遇到了一个问题,即验证是在.Created方法的末尾,它在将文件复制到目标文件之前访问该文件进行一些验证。当我到达这一点时,如果文件很大并且仍然处于从源文件复制的过程中,它将返回一个io“文件已被使用”的错误。

我想要做的是完成所有的初步代码,然后我希望线程“挂起”,直到该文件的.Changed方法触发指示文件完成,因为我只捕获更改最后一个访问过滤器。

回答

1

我会设置一个单独的线程使用生产者 - 消费者模式,监视项目出现在队列中。这些项目将代表文件更改并包含诸如文件路径和发生的更改类型等信息。您的事件处理程序只会将项目发布到队列中,并让消费者线程出列并处理信息。这会将您需要的处理从文件系统通知事件中分离出来,从而更容易避免出现“正在使用的文件”问题。

+0

+1,表示同意。但起皱:它不是典型的生产者 - 消费者模式。操作成功后才能使用。 – 2010-11-03 21:21:47

+0

是的,绝对有一些棘手的细节需要解决...... – 2010-11-05 02:41:51

2

使用可以使用ManualResetEvent。 Created方法可以完成它的工作,然后等待Created方法可以继续的Changed事件信号。

1

这个问题很正常,当其他进程忙于写入文件时,通常无法打开该文件。你需要等待,你无法预测什么时候会完成。将文件路径添加到列表中,并使用计时器清空该列表,并定期重试该操作。小心逻辑,你使用线程,所以你需要用锁来保护列表。

+0

我确实考虑过一个涉及计时器的模型,但我真的宁愿不使用计时器或任何类型的循环。我知道他们是有效的,但我试图将我的编程风格推向事件驱动的调用。 – Patrick 2010-11-04 12:26:54

+0

好吧,如果你足够了解写入文件的过程,那么你可能不会使用FSW。 – 2010-11-04 12:39:04

+0

该过程本身需要能够处理20-30个不同的文件,并将它们放置在所需的位置......这也不是项目特定的功能。这是现在和将来将继续在整个公司的多个不同项目中使用的东西。 – Patrick 2010-11-04 13:15:58

1

请注意,NotifyFilters.LastAccess并不意味着您会知道何时其他进程已完成文件。它只是意味着当文件的上次访问时间发生变化时您会收到通知。

我通常会与Brian Gideon的生产者 - 消费者模式一起去。这也可以很容易地过滤掉FileSystemWatcher愉快举动的(典型)多个事件。

(几乎)确定其他进程已完成文件的唯一方法是试图获取排它锁。虽然这并不总是足够的。我见过一个FTP服务器,它关闭并重新打开它写入的每个块的文件;-)

请注意,FileSystemWatcher确实有一个内部缓冲区,用于缓冲它从Windows获得的文件通知,但如果很多事情发生,这个缓冲区可能会溢出。这也是创建生产者 - 消费者的原因。

我通常会通过创建一个例程来修改此问题,该例程可以手动扫描观看的目录,然后稍后运行一次。是的,民意调查;-)

有了这个例程也是很好的时候启动你的应用程序。文件可能已经到达,而它已经关闭了!