C# 使用Directory.GetFiles()或枚举包含锁定文件的目标目录的文件的最佳实践?
目前,我试图改进两个windows服务(C#)的设计。 服务A生成数据导出(csv文件)并将其写入临时目录。 因此,该文件被写入一个临时目录,该目录是一个子目录。主输出目录的。 然后文件被移动(通过C# 使用Directory.GetFiles()或枚举包含锁定文件的目标目录的文件的最佳实践?,c#,filesystems,.net,C#,Filesystems,.net,目前,我试图改进两个windows服务(C#)的设计。 服务A生成数据导出(csv文件)并将其写入临时目录。 因此,该文件被写入一个临时目录,该目录是一个子目录。主输出目录的。 然后文件被移动(通过file.Move)到输出目录(成功写入后)。 此导出可以由多个线程执行 另一个服务B尝试在定义的时间间隔内从此输出目录获取文件。 如何确保Directory.GetFiles()排除锁定的文件 我应该通过创建一个新的文件流(使用 (Stream=newfilestream(“MyFilename.t
file.Move
)到输出目录(成功写入后)。
此导出可以由多个线程执行
另一个服务B尝试在定义的时间间隔内从此输出目录获取文件。
如何确保Directory.GetFiles()
排除锁定的文件
Stream=newfilestream(“MyFilename.txt”,FileMode.Open)
)作为
描述
一种方法是在文件使用时从writing应用程序中将其标记为临时文件,并且仅在文件写入并关闭后才取消标记,例如
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)在驱动器、分区或作为子目录装入的其他媒体之间肯定不起作用。操作系统在后台执行复制+删除操作,而不是目录条目编辑。(2)这种行为是一种惯例,而不是规则。尽管我从未见过它,但文件系统可以随意破坏它,甚至可以不一致地破坏它
因此,这可能会奏效。如果不行,我建议您使用自己的临时扩展(我以前也这样做过,但在客户端和服务器之间,只能通过共享驱动器进行通信),这样做并没有那么困难,而且工作得完美无缺
如果你自己的想法技术含量太低,并且你在同一台机器上(听起来像是),你可以设置一个互斥(谷歌),嵌入文件名,在文件写入过程中,文件名在写入进程中存在;然后在打开从另一个进程读取的每个文件时,对文件名进行阻塞测试。如果希望第二个进程尽快响应,请将此与文件系统监视程序结合起来。然后拍拍自己的背,因为它花费了与e temp文件名idea,无额外增益>:-}
祝你好运!为什么不在输出目录上使用
FileSystemWatcher
?这样,当文件放在那里时,服务B会立即得到通知,而不必担心扫描.RE FileSystemWatcher-如果在创建文件时而不是关闭文件时触发,它实际上可能比定期轮询更糟糕,如“B”w当文件被锁定时,您很可能会跟踪它。文件可能会在第1行之后但在第3行之前被“B”击中。此外,当通过File.move写入文件时,这种类型的控件是不可能的。注意到了。我想您可以在B监视器所在的不同目录中创建该文件,并在移动它之前将其设置为临时-然后在在移动完成后向您致敬。确实如此。移动可能会保留属性(希望是原子的)。是的,我决定使用临时文件扩展名。到目前为止效果非常好。感谢讨论此主题。