You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多实例并行运行的C#程序如何锁定文件避免重复处理?

C#多实例文件导入数据库的线程安全解决方案

1. 避免实例间重复选取文件

核心思路是给已被选中的文件加唯一标识,让其他实例能识别并跳过。最实用的两种方式:

方式1:文件重命名标记

选中文件后立即给它重命名(比如添加 .processing 后缀),其他实例扫描文件夹时只处理无该后缀的文件。处理完成后,再将文件移到processed文件夹或删除标记后缀。

// 尝试标记文件,成功则返回true表示可处理
bool TryMarkFile(string filePath)
{
    var tempPath = filePath + ".processing";
    try
    {
        // 原子性重命名,避免多实例竞争
        File.Move(filePath, tempPath);
        // 处理完后记得把tempPath改回原路径或移走
        return true;
    }
    catch (IOException)
    {
        // 其他实例已经抢先标记,跳过该文件
        return false;
    }
}

方式2:共享状态记录

用一个共享存储(比如数据库表、本地JSON文件)记录已选中的文件路径。每个实例选取文件前先查询该状态,更新时必须加锁:

  • 如果用数据库:给状态表加行级锁,或者用SELECT ... FOR UPDATE语句确保原子性。
  • 如果用本地文件:操作状态文件时用FileShare.None打开,确保同一时间只有一个实例能修改状态。

2. 锁定选中的文件

确保选中的文件不会被其他实例读取或修改,有两种可靠方式:

方式1:独占文件流锁定

打开文件时指定FileShare.None,这样其他实例无法打开该文件,直到当前实例关闭流:

using (var fileStream = new FileStream(
    filePath, 
    FileMode.Open, 
    FileAccess.Read, 
    FileShare.None))
{
    // 读取文件内容、导入数据库的逻辑
}
// 流关闭后,文件自动解锁

方式2:结合重命名的锁定

重命名操作本身就是一种轻量锁定——因为Windows系统中,正在被重命名的文件无法被其他进程修改。配合.processing后缀,既能标记已选中,又能防止其他实例操作。

3. 实现全流程线程安全

把上述方法组合起来,加上异常回滚,确保整个处理过程无冲突:

  1. 批量扫描,逐个抢占:不要一次性选取10个文件,而是扫描到文件后逐个尝试标记(重命名),成功标记的才加入处理队列,失败就跳过。
  2. 标记+锁定双重保障:标记文件后,用独占流打开文件,确保从选中到处理的全程独占。
  3. 异常回滚:如果处理过程中抛出异常,要把标记的文件恢复(比如把.processing后缀去掉),避免文件被永久锁定:
void ProcessFile(string filePath)
{
    var tempPath = filePath + ".processing";
    bool isMarked = false;
    try
    {
        // 第一步:标记文件
        File.Move(filePath, tempPath);
        isMarked = true;

        // 第二步:独占打开文件
        using (var fs = new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.None))
        {
            // 导入数据库逻辑
            ImportToDatabase(fs);
        }

        // 第三步:处理完成,移到已完成文件夹
        File.Move(tempPath, Path.Combine("processed", Path.GetFileName(filePath)));
    }
    catch (Exception ex)
    {
        // 异常回滚:恢复标记的文件
        if (isMarked && File.Exists(tempPath))
        {
            File.Move(tempPath, filePath);
        }
        // 记录日志
        Console.WriteLine($"处理文件失败:{ex.Message}");
    }
}
  1. 限制并发数:每个实例内部可以用SemaphoreSlim限制同时处理的文件数(比如10个),避免单个实例占用过多资源。

内容的提问来源于stack exchange,提问作者papoxe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:55:17