在不阻止其他进程同时读取文件的情况下读取文件
本文关键字:文件 读取 情况下 进程 其他 | 更新日期: 2023-09-27 18:00:43
我正在C#/.NET中制作一个小应用程序,用于监视文件的创建,当创建文件时,它会获取内容,解析并将其写入另一个文件。
到目前为止一切都很好。但问题是:还有另一个进程也在监视这个文件。我的过程只是读取文件,而第二个过程读取它,然后删除它。
我的应用程序正在完成它的工作,但当它读取文件时,其他进程无法读取它,并完全崩溃(不是我创建的,也没有修复它的来源)。
我的应用程序运行得很快,其他人打开文件的时间很短,以获取内容并将其放入变量中,这样它就可以更快地关闭文件,然后解析变量中文件的内容。
我显然不知道该怎么做,但我希望能够阅读该文件,并让另一个人同时阅读该文件而不会出现任何问题。有可能吗?我仍然认为,在其他应用程序完成解析后,文件被删除的事实会有问题…
有什么建议或想法吗?
非常感谢!
您可以按如下方式打开文件,以确保您不会从其他进程锁定它:
using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
// do your stuff
}
但是,如果其他进程试图以独占模式打开它,它将无济于事,而且它仍然会崩溃。除了修复其他进程的代码之外,没有其他方法可以解决这个问题。
KISS:你能在第一个程序不在看的位置创建文件,但你的软件在看吗?当你处理完它后,你会把它移到第一个程序正在看的当前位置吗?
否则:您将面临争论,因为这将是一场竞赛,看哪个进程真正首先"注意到"文件并开始工作。
我想你对创建文件的过程也没有任何控制权?
在这种情况下,您可能会查看PsSuspend或PauseSp——如果您可以通过暂停它来控制另一个进程,直到您准备好(处理文件),那么这可能是可行的。不确定这会有多稳健。
还有一个潜在的竞争条件是"注意到"文件并执行一个操作(无论它是什么)——让另一个进程永远暂停,直到你希望它运行(或者杀死它并启动它),这是在限制范围内实现你想要的唯一完全确定的方式。
如果您使用的是NTFS驱动器(很可能),那么您可以创建一个指向该文件的硬链接。从本质上讲,这是在不实际创建副本的情况下复制文件。你可以通过硬链接读取文件。另一个进程可以删除该文件,这只会删除它们与该文件的链接。这样会将文件保留在适当的位置供您阅读。当你的程序读取完文件后,它可以删除硬链接,文件系统会看到这两个链接都被删除了,它会删除文件本身。
这可以通过从命令行完成
fsutil hardlink create <NewFileName> <ExistingFileName>
也可以在Windows API中p/Invoke CreateHardLink
函数。
您可以创建另一个名为.reading文件的空零字节文件吗?该文件具有相同的名称,但扩展名为"reading"。然后,一旦第一个进程完成读取文件,请将.reading重命名为.done,第二个进程可以检查.done文件并删除原始文件,因为.done和原始文件都具有相同的名字,但扩展名称不同?。
@Prashant的回应给了我灵感,这很相似,但我相信会解决你的问题。
如果其他进程必须匹配某个文件名模式
- 将文件重命名为不会首先匹配,非常便宜/快速操作
- 完成后将其重命名回
如果它匹配给定文件夹中的每个文件
- 将其移动到另一个文件夹(在大多数文件系统中也是一种非常便宜的操作)
- 完成后将其移回
如果其他进程已经锁定了你的文件(即使是为了读取),那么你的进程就会失败,你可以让它变得优雅。如果没有,你应该是安全的。
当然,仍然有比赛条件的可能性,但这应该比你现在做的安全得多。