我有一个程序作为Windows服务运行,它处理特定文件夹中的文件.
由于它是一项服务,它会不断监视文件夹中是否添加了新文件.该程序的部分工作是执行目标文件夹中文件的比较并标记不匹配的文件.
我想要做的是检测正在运行的复制操作以及何时完成,以便在匹配文件尚未复制到目标文件夹时,文件不会过早地被标记.
我FileSystemWatcher想要做的是使用它来观察目标文件夹,看看是否正在进行复制操作.如果有,我将程序的主线程置于睡眠状态,直到复制操作完成,然后继续像正常一样对文件夹执行操作.
我只想对这种方法有所了解,看看它是否有效.如果其他人有任何其他独特的方法来解决这个问题,我们将不胜感激.
更新:
我为这个混乱道歉,当我说目标目录时,我的意思是包含我想要处理的所有文件的源文件夹.我的程序的一部分功能是将源目录的目录结构复制到目标目录,并将所有有效文件复制到该目标目录,保留原始源目录的目录结构,即用户可以复制包含文件的文件夹到源目录.我想通过确保将包含更多子文件夹和文件的新文件夹集复制到源目录进行处理来防止错误,我的程序在复制过程完成之前不会开始在目标目录上运行.
jas*_*son 11
是的,使用a FileSystemWatcher而不是观察创建的事件,观察已更改的事件.每次触发后,尝试打开文件.像这样的东西:
var watcher = new FileSystemWatcher(path, filter);
watcher.Changed += (sender, e) => {
FileStream file = null;
try {
Thread.Sleep(100); // hack for timing issues
file = File.Open(
e.FullPath,
FileMode.Open,
FileAccess.Read,
FileShare.Read
);
}
catch(IOException) {
// we couldn't open the file
// this is probably because the copy operation is not done
// just swallow the exception
return;
}
// now we have a handle to the file
};
Run Code Online (Sandbox Code Playgroud)
不幸的是,这是你能做的最好的事情.没有干净的方法知道文件已准备好供您使用.
您正在寻找的是典型的生产者/消费者场景。本页的“生产者/消费者队列”部分概述了您需要执行的操作 。这将允许您使用多线程(可能跨越后台工作程序)来复制文件,这样您就不会阻止主服务线程侦听系统事件,并且您可以在那里执行更有意义的任务 - 例如检查新文件和更新队列。很快。 根据个人经验(已实现此任务),除非您在多 CPU 计算机上运行,否则这种方法不会带来太多性能增益,但该过程非常干净和流畅+代码在逻辑上很好地分离。on main thread do check for new filesbackground threads perform the actual coping task
简而言之,您要做的就是拥有一个如下所示的对象:
public class File
{
public string FullPath {get; internal set;}
public bool CopyInProgress {get; set;} // property to make sure
// .. other properties if desired
}
Run Code Online (Sandbox Code Playgroud)
然后按照上面发布的教程对文件对象和队列发出锁定以更新它并复制它。使用这种方法,您可以使用这种类型的方法,而不是不断监视文件复制完成情况。这里要认识到的重要一点是,您的服务每个实际物理文件只有一个 File 对象实例 - 只需确保 (1) 在添加和删除时锁定队列 & (2) 在初始化更新时锁定实际 File 对象。
EDIT:上面我说“这种方法不会带来太多的性能增益,除非”我指的是如果你在单线程中执行这种方法,与@Jason的建议相比,由于@Jason的解决方案执行非常昂贵的IO,这种方法必须明显更快在大多数情况下会失败的操作。我还没有测试过,但我很确定,因为我的方法不需要 IO 操作打开(仅一次)、流(仅一次)和关闭文件(仅一次)。@Jason 方法建议进行多个打开,打开,打开,打开操作,除了最后一个之外,这些操作都会失败。