我们有一个长期运行的旧Windows应用程序,由于各种原因无法更新。该程序以不可预测的间隔写出数据文件。在写出新数据文件之前,它首先重命名以前的数据文件。
其他应用程序(好吧,至少有一个!)需要实时访问最新的数据文件。问题是如果读取器程序在编写器程序尝试重命名时打开文件,则编写器程序崩溃。这绝不可能发生!
解决编写程序的明显解决方案是不切实际的。我想要找到的是一些Windows服务或替代文件系统,它们可以在写入时透明地复制文件。通过这种方式,读者程序可以访问复制的文件而不会干扰编写器程序(如果读取器程序出现错误,则更为重要)。
据我所知,磁盘镜像无法解决我们的文件锁定问题。
我的问题:有没有人知道我们可以使用这样的服务?
编辑:说明问题的示例代码,即使假定非锁定文件读取:
const string SrcFilePath = @"C:\Foo.txt";
const string DestFilePath = @"C:\Bar.txt";
void Main()
{
Task.Run(() =>
{
while (true)
{
try
{
Console.WriteLine("Writer: moving {0} to {1}", SrcFilePath, DestFilePath);
File.Move(SrcFilePath, DestFilePath);
Console.WriteLine("Writer: writing {0}", SrcFilePath);
File.WriteAllText(SrcFilePath, "Hello, World!\n");
}
catch (Exception e)
{
Console.WriteLine("Writer: error: {0}", e.Message);
}
Console.WriteLine("Writer: sleeping.");
Task.Delay(1000).Wait();
}
});
Task.Run(() =>
{
while (true)
try
{
Console.WriteLine("Reader: opening {0}", SrcFilePath);
var fs = new FileStream(SrcFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Console.WriteLine("Reader: sleeping...");
Task.Delay(1500).Wait(); // Simulate a context switch in the middle of a file read.
Console.WriteLine("Reader: waking up.");
Console.WriteLine("Reader: closing {0}", SrcFilePath);
fs.Dispose();
}
catch (Exception e)
{
Console.WriteLine("Reader: error: {0}", e.Message);
}
});
}
这样就失败了:
Reader: opening C:\Foo.txt
Reader: sleeping...
Writer: moving C:\Foo.txt to C:\Bar.txt
Writer: error: The process cannot access the file because it is being used by another process.
Writer: sleeping.
Reader: waking up.
Reader: closing C:\Foo.txt
答案 0 :(得分:0)
要移动文件,共享模式必须允许您删除它。在这种情况下,这意味着FileShare.Delete
选项。
答案 1 :(得分:0)
NTFS有一个名为“卷影复制”的有趣功能,可让您在使用硬盘时拍摄硬盘的快照。当其他应用程序写入HDD时,这些更改将存储在另一个HDD扇区中,而卷影副本仍将包含创建卷影副本时的数据。你的主要缺点是 - 他们初始化的速度相对较慢,如果“实时”你的意思是你需要每秒查询一次数据,那么恐怕这种方法对你不起作用。然而,这是最可靠和最不分散注意力的方式。 Here’s some guide
另一种可能适合您的方法。每次您想要阅读数据时:
这样,即使您使用备用路径读取相同的数据,编写器进程也应该能够正确地重命名文件。