CSharp - 在 C# 中,如果 2个进程正在读取和写入同一个文件,那么避免进程锁定异常的最佳方法是什么?

使用以下代码读取文件:


using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.None))
{
 using (TextReader tr = new StreamReader(fileStream))
 {
 	string fileContents = tr.ReadToEnd();
 }
}

下面的文件写入代码:


using (TextWriter tw = new StreamWriter(fileName))
{
 tw.Write(fileContents);
 tw.Close();
}

下面是以下异常详细信息:

the process cannot access the file'c:tempmyfile.txt'because it is being used by another process .

避免这种情况的最好方法是什么?

时间:

你可以打开一个文件,以便写入并锁定写入访问,从而允许其他人仍然读取文件。

例如,


using (FileStream stream = new FileStream(@"C:Myfile.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.Read))
{
 // Do your writing here.
}

其他文件访问只打开读取和不写入的文件,并允许读写。


using (FileStream stream = new FileStream(@"C:Myfile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
 // Does reading here.
}

如果你创建一个已经命名的互斥体,你可以在写入应用程序中定义互斥体,并让读取应用程序等待直到释放了互斥。

所以在当前使用FileSystemWatcher的通知进程中,只需检查是否需要等待互斥锁,如果你愿意,它将等待,然后处理。

这是vb互斥这样的例子,我发现,它应该是 C# 容易转换。

使用 FileShare.None 打开文件有什么特殊原因? 这将阻止任何其他进程打开该文件。

FileShare.Write 或者 FileShare.ReadWrite 应该允许其他进程( 服从权限) 在读取文件时打开并写入文件,但是在读取文件时,你必须监视文件的更改- 在打开时对内容进行简单的缓冲。

所有这些答案,然而,同样有效,最好的解决方案取决于你想做什么与 file: 如果读是很重要的,同时保证它不会改变,并且处理后续的异常在你编写代码;如果读和写是很重要的,它在同一时间,然后改变文件共享常数。

你可以在这里使用Mutex对象。

应将FileShare设置为FileShare.read,并为writer设置为FileShare.none ,这应该确保在写入过程中reader不会读取文件。

reader(排除重试)变成了


using (FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
 using (TextReader tr = new StreamReader(fileStream))
 {
 string fileContents = tr.ReadToEnd();
 }
}

writer (排除重试)变成:


FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None);
using (TextWriter tw = new StreamWriter(fileStream))
{
 tw.Write(fileContents);
 tw.Close();
}

使你的进程在写入文件时检查该文件的状态。 你可以通过一个锁定文件来完成这里操作( 例如 。 这里文件的存在,可以是空的,可以防止写入主文件。

尽管这不是安全的,因为这两个进程可能同时创建锁文件- 但是你可以在提交写入之前检查它。

如果你的进程遇到一个锁文件,那么让它简单地休眠/等待,然后在以后的一个预定时间间隔内重试。

写入临时文件时,完成重命名/移动文件到读取器正在查找的位置和/或者名称。

最好的做法是把一个应用程序协议放在文件传输/所有权转移机制之上。 "lock-file"机制是一个老的UNIX hack,它已经存在多年了。 最好的办法就是把文件放到读。 有很多方法可以做到这一点。 你可以用随机文件名创建文件,然后使用"给"将它的命名为。 这将允许编写器异步写入另一个文件。 考虑"网页"的工作原理。 网页有一个"链接"到它的更多信息,用于图像,脚本,外部内容 等等,服务器给你这个页面,因为它是你想要的"资源"视图。 然后,你的浏览器会根据页面描述( HTML文件或者其他返回的内容) 来获取适当的内容,然后传输它需要的内容。

这是使用的最弹性的"共享"机制。 写入文件,共享名称,移动到下一个文件。 "共享名称"部件,是原子的指针,确保双方( 读者和作者) 都同意内容是"完成。"


static double GetFileSize(string path) { 

 FileInfo info = new FileInfo(path);

 if (!info.Exists)
 return 0;

 return (double)info.Length;
 }

...