目前我尝试改进两种Windows服务(C#)的设计。
服务A生成数据导出(csv文件)并将其写入临时目录。
因此,文件将写入作为子目录的临时目录。主输出目录。
然后将文件(通过 File.Move
)移动到输出目录(成功写入后)。
此导出可以由多个线程执行。
另一个服务B尝试在定义的时间间隔内从此输出目录中获取文件。
如何确保 Directory.GetFiles()
排除锁定的文件。
我是否应该尝试通过创建新的FileStream来检查每个文件(使用
(Stream stream = new FileStream("MyFilename.txt", FileMode.Open)
)as
描述
here
或者生产者服务(A)是否应该使用临时文件名(* .csv.tmp) 消费者服务(B)自动排除适当的搜索模式。移动完成后重命名文件。
答案 0 :(得分:0)
一种方法是在使用时将文件标记为临时写入应用程序,并且只有在写入和关闭时才将其标记为未标记,例如。
FileStream f = File.Create (filename);
FileAttributes attr = File.GetAttributes (filename);
File.SetAttributes (filename, attr | FileAttributes.Temporary);
//write to file.
f.Close ();
File.SetAttributes (filename, attr);
从消费应用中,您只想跳过任何临时文件。
foreach (var file in Directory.GetFiles (Path.GetDirectoryName (filename))) {
if ((File.GetAttributes (file) & FileAttributes.Temporary) != 0) continue;
// do normal stuff.
}
答案 1 :(得分:0)
咦?怎么会这样?
如果文件在同一个驱动器上,则Move操作是原子的!该操作实际上是重命名,从前一个目录条目中删除,并将其插入到下一个目录中,指向数据实际所在的相同扇区(或whatevers),而不重写它。文件系统的内部锁定机制必须锁定&阻止目录在此过程中读取,以防止目录扫描返回损坏的结果。
这意味着,当它出现在目录中时,它将不会被锁定;实际上,自从将其写入上一个目录的关闭操作以来,该文件将不会被打开/修改。
警告 - (1)绝对不能在驱动器,分区或作为子目录安装的其他媒体之间工作。操作系统在后台执行复制+删除而不是目录条目编辑。 (2)这种行为是一种惯例,而不是一种规则。虽然我从来没有见过它,但是文件系统可以自由地打破它,甚至可以不一致地打破它!
所以这可能会奏效。如果没有,我建议使用你自己的临时扩展的想法(我之前已经完成了这个目的,但在客户端和服务器之间只能通过共享驱动器进行通信)并且它不是那样的努力工作,完美无缺。
如果你自己的想法太低技术,并且你在同一台机器上(听起来像你),你可以设置一个嵌入文件名的互斥锁(谷歌那个),当文件存在时写作,在作家过程中;然后在打开从其他进程读取的每个文件时对其执行阻止测试。如果您希望第二个进程响应ASAP将其与文件系统观察器结合起来。然后拍拍自己的背部,花费十倍的时间作为临时文件名的想法,没有额外的收益>: - }
祝你好运!