在C#的文件操作场景中,当多个进程或线程需要访问同一个文件时,为了避免数据读写冲突,通常需要对文件进行锁定。但默认的文件锁定操作会一直阻塞直到锁定成功,这在很多业务场景下并不适用,我们需要实现尝试锁定文件,若超过指定时间仍未成功则自动放弃的逻辑。

C#文件锁定的基础原理
C#中主要通过FileStream类来实现文件锁定,其核心是利用Windows系统的文件句柄锁机制。当我们打开一个文件并指定共享模式时,就可以控制其他进程对该文件的访问权限。常用的共享模式参数有两个:
- FileShare.None:打开文件时不允许其他任何进程读写该文件,相当于独占锁定
- FileShare.Read:打开文件时允许其他进程读取该文件,但禁止写入
默认情况下,使用FileStream打开文件时如果文件已经被锁定,会直接抛出异常,或者一直等待直到文件可用,这取决于我们使用的打开方式。
超时机制的实现思路
要实现超时后放弃锁定的逻辑,核心思路是在指定的超时时间内,循环尝试打开并锁定文件,每次尝试失败后等待一小段时间再重试,如果累计等待时间超过设定的超时阈值,就终止尝试并返回失败结果。具体步骤如下:
- 记录尝试开始的时间戳
- 进入循环尝试逻辑,每次尝试打开文件并锁定
- 如果锁定成功,返回对应的
FileStream对象 - 如果锁定失败,计算当前已消耗的时间,若超过超时时间则退出循环返回失败
- 若未超过超时时间,等待指定的重试间隔后继续尝试
完整实现代码示例
下面是一个封装好的文件锁定超时工具类,支持设置超时时间和重试间隔,代码如下:
using System;
using System.IO;
using System.Threading;
public class FileLockHelper
{
/// <summary>
/// 尝试锁定文件,超时后放弃
/// </summary>
/// <param name="filePath">要锁定的文件路径</param>
/// <param name="timeoutMilliseconds">超时时间,单位毫秒</param>
/// <param name="retryIntervalMilliseconds">重试间隔,单位毫秒</param>
/// <param name="fileStream">输出锁定成功的文件流</param>
/// <returns>是否锁定成功</returns>
public static bool TryLockFile(string filePath, int timeoutMilliseconds, int retryIntervalMilliseconds, out FileStream fileStream)
{
fileStream = null;
// 记录开始时间
DateTime startTime = DateTime.Now;
while (true)
{
try
{
// 尝试以独占模式打开文件,如果文件被占用会抛出异常
fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
// 打开成功,返回true
return true;
}
catch (IOException)
{
// 计算已消耗的时间
TimeSpan elapsed = DateTime.Now - startTime;
// 如果超过超时时间,退出循环
if (elapsed.TotalMilliseconds >= timeoutMilliseconds)
{
return false;
}
// 未超过超时时间,等待重试间隔后继续尝试
Thread.Sleep(retryIntervalMilliseconds);
}
}
}
}
使用示例
下面是如何使用上述工具类进行文件锁定超时的示例:
class Program
{
static void Main(string[] args)
{
string targetFile = "test.txt";
// 设置超时时间为3秒,重试间隔为500毫秒
int timeout = 3000;
int retryInterval = 500;
if (FileLockHelper.TryLockFile(targetFile, timeout, retryInterval, out FileStream fs))
{
try
{
Console.WriteLine("文件锁定成功,可以进行读写操作");
// 这里编写文件读写逻辑
byte[] content = System.Text.Encoding.UTF8.GetBytes("测试内容");
fs.Write(content, 0, content.Length);
fs.Flush();
}
finally
{
// 操作完成后释放文件流,解除锁定
fs?.Dispose();
Console.WriteLine("文件锁定已释放");
}
}
else
{
Console.WriteLine("文件锁定超时,放弃操作");
}
}
}
注意事项
在实际使用该机制时,需要注意以下几点:
- 重试间隔不要设置得太短,否则会频繁触发异常,消耗过多CPU资源,建议设置在100毫秒以上
- 锁定文件后一定要在finally块中释放
FileStream对象,否则会导致文件一直被锁定,其他进程无法访问 - 如果文件不存在,上述代码会自动创建文件,如果不需要该逻辑,可以在尝试锁定前先判断文件是否存在
- 该机制仅对通过
FileShare.None方式锁定的文件有效,如果其他进程使用了更宽松的共享模式打开文件,可能无法正确检测到占用情况
扩展说明
如果需要更精细的锁定控制,比如支持读写锁分离,或者需要跨进程的锁状态同步,可以结合互斥量Mutex来实现。互斥量是系统级别的同步对象,支持跨进程使用,并且自带等待超时机制,使用起来更加方便。不过互斥量适合用于进程级别的同步,对于单个文件的操作,还是优先使用FileStream的锁定方式更轻量。
C#文件锁定FileStream超时机制文件操作lock_timeout修改时间:2026-07-05 10:30:25