我正在开发一个.net应用程序,我正在使用FileSystemWatcher类并将其Created事件附加到文件夹上。我必须对此事件采取行动(即将文件复制到其他位置)。当我将大尺寸放入附加的监视文件夹时,即使文件复制过程仍未完成,事件立即引发。我不想通过file.open方法检查这个。
有没有办法通知我的文件复制过程已经完成,然后我的事件就会被激活。
答案 0 :(得分:4)
当一个新文件完全创建时,FileSystemWatcher(和底层的ReadDirectoryChangesW API)无法获得通知,这确实是一件令人失望的事。
到目前为止,我遇到的最好和最安全的方法(并且不依赖于计时器)是这样的:
收到Created事件后,启动一个线程,该线程在循环中检查文件是否仍然被锁定(使用适当的重试间隔和最大重试次数)。检查文件是否被锁定的唯一方法是尝试使用独占访问权限打开它:如果成功(不抛出IOException),则文件完成复制,并且您的线程可以引发适当的事件(例如FileCopyCompleted)。
答案 1 :(得分:2)
我遇到了完全相同的问题,并以这种方式解决了问题:
FileSystemWatcher
以便在修改文件时通知和。收到通知时:
一个。如果没有为此文件名设置计时器(见下文),请将计时器设置为以适当的间隔到期(我通常使用1秒)。
湾如果为此文件名设置了计时器,请取消计时器并将新计时器设置为在相同的时间间隔内到期。
当计时器到期时,您知道相关文件已创建或修改,并且在时间间隔内未受影响。这意味着可能已完成复制/修改,您现在可以对其进行处理。
答案 2 :(得分:1)
您可以侦听修改后的事件,然后启动计时器。如果再次引发修改后的事件,请重置计时器。当计时器达到某个值而没有引发修改事件时,您可以尝试执行复制。
答案 3 :(得分:1)
我订阅了Changed
- 和Renamed
- 事件,并尝试在每个Changed
上重命名该文件 - 捕获IOExceptions的事件。如果重命名成功,则副本已完成,Rename
- 事件仅触发一次。
答案 4 :(得分:1)
FileSystemWatcher存在三个问题,第一个问题是它可以发送重复的创建事件,因此您可以通过以下方式检查:
this.watcher.Created += (s, e) =>
{
if (!this.seen.ContainsKey(e.FullPath)
|| (DateTime.Now - this.seen[e.FullPath]) > this.seenInterval)
{
this.seen[e.FullPath] = DateTime.Now;
ThreadPool.QueueUserWorkItem(
this.WaitForCreatingProcessToCloseFileThenDoStuff, e.FullPath);
}
};
其中this.seen
是Dictionary<string, DateTime>
而this.seenInterval
是TimeSpan
。
接下来,您必须等待文件创建者完成编写(问题中提出的问题)。第三,你必须要小心,因为有时文件创建事件会在文件被打开之前被抛出而不会给你FileNotFoundException
,但它也可以被移除然后你可以获得它同时给出一个{ {1}}。
FileNotFoundException
当然,您可以设置自己的超时时间。此代码留有足够的时间挂5分钟。如果请求,真实代码也会有一个标志来退出线程。
答案 5 :(得分:0)
尝试设置过滤器
myWatcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite;
答案 6 :(得分:0)
这个答案有点晚了,但是如果可能的话,我会让源进程在大文件或文件之后复制一个小标记文件并在其上使用FileWatcher。