为何设置FileShare.Read后第二个进程仍无法读取.lock文件?
问题原因分析
第二个进程文件打开的共享模式不兼容
第一个进程打开.lock文件时指定了FileShare.Read,允许其他进程以只读方式访问该文件。但第二个进程调用File.Open时未显式设置FileShare参数,默认值为FileShare.None(要求独占文件),这与第一个进程的共享权限规则冲突,直接触发IOException。Unlock操作无意义导致报错File.Open创建的文件流默认不会对文件加锁,只有主动调用Lock方法锁定文件后,才能执行解锁操作。直接调用Unlock会因文件从未被锁定而抛出“已解锁”的异常。
解决方法
1. 修正第二个进程的文件打开参数
在第二个进程打开.lock文件时,显式指定FileShare.Read,确保共享模式与第一个进程的规则兼容:
// 替换catch块中的打开代码 using (var infofile = File.Open(lockFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
2. 优化第一个进程的逻辑(可选但关键)
- 移除多余的
File.Delete操作:FileMode.CreateNew会在文件已存在时自动抛出异常,无需提前删除,避免干扰正在运行的第一个进程。 - 确保写入的用户信息立即落盘:在
StreamWriter的using块内添加Flush(),防止第二个进程读取到不完整的内容:
using (var writer = new StreamWriter(lockfile, Encoding.UTF8, 256, true)) { string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name; writer.WriteLine(userName); writer.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); writer.Flush(); // 强制将缓存数据写入磁盘 }
3. 删除无效的Unlock调用
直接移除lockfile.Unlock(0,lockfile.Length);这行代码,因为文件流默认未加锁,该操作没有实际意义。
完整修正代码
using System; using System.IO; using System.Text; using System.Security.Principal; namespace SingleUser { internal class Program { static void Main(string[] args) { string lockFileName = ".lock"; try { // 第一个进程创建文件,允许其他进程只读访问 using (var lockfile = File.Open(lockFileName, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read)) { using (var writer = new StreamWriter(lockfile, Encoding.UTF8, 256, true)) { string userName = WindowsIdentity.GetCurrent().Name; writer.WriteLine(userName); writer.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); writer.Flush(); // 确保数据写入磁盘 } Console.WriteLine("You can access the data. Press Enter to stop working with the file."); Console.ReadLine(); } } catch (IOException) { // 第二个进程读取锁定信息 try { using (var infofile = File.Open(lockFileName, FileMode.Open, FileAccess.Read, FileShare.Read)) { using (var reader = new StreamReader(infofile, Encoding.UTF8, false, 256, true)) { string user = reader.ReadLine(); string time = reader.ReadLine(); if (!string.IsNullOrEmpty(user) && !string.IsNullOrEmpty(time)) { Console.WriteLine($"{user} works on the file since {time}."); } else { Console.WriteLine("The file is locked by another user, but lock info is incomplete."); } } } } catch (IOException innerEx) { Console.WriteLine($"Failed to read lock info: {innerEx.Message}"); } Console.WriteLine("You can't modify the data. Press Enter to stop."); Console.ReadLine(); } } } }
额外说明
- 若要处理进程异常退出后
.lock文件残留的情况,可在第一个进程启动时尝试以独占方式打开.lock文件,判断是否有其他进程占用,再决定是否删除残留文件。 - 网络文件场景下,需确保操作系统层面的文件共享权限配置正确,避免额外的访问限制。
内容的提问来源于stack exchange,提问作者Thomas W.
相关产品推荐
相关产品推荐

