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

异步从API下载JSON保存到文件时出现进程占用文件错误如何解决

核心问题定位

你遇到的错误不是多线程共享流导致的,根源是C# 循环变量闭包捕获的经典问题:
你在循环外部定义了计数变量i,传入Task.Run的lambda表达式捕获的是i的引用,而非每次循环时的瞬时值。当任务实际被调度执行时,循环已经完成了多轮自增,多个任务会拿到相同的i值,进而尝试写入同一路径的JSON文件。而你打开文件时设置了FileShare.None参数,不允许其他线程/进程同时访问该文件,因此直接抛出文件被占用的异常。

修复方案

在循环内部定义临时变量存储当前循环的计数,确保每个lambda捕获的是独立的计数变量:

public override async Task ExecuteCommandAsync(IEnumerable<string> urls)
{
    string directory = "some directory";
    int i = 0;
    foreach (var url in urls)
    {
        // 循环内部定义临时变量,每次循环生成独立的副本供lambda捕获
        int currentIndex = i;
        tasks.Add(Task.Run(async () =>
        {
            try
            {
                await DownloadJsonFromUrl(url, directory, currentIndex);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }));
        i++;
        Console.WriteLine($"task nr {i} started.");
    }
    await Task.WhenAll(tasks);
}
其他可能的触发因素
  • 路径拼接逻辑存在缺陷,比如directory变量末尾没有添加路径分隔符(Windows下为\,Linux下为/),如果目录末尾的字符和数字拼接后和其他文件名重合,会意外触发重名冲突
  • 外部进程锁定了目标文件,比如杀毒软件、文件同步工具正在扫描对应目录,可将FileShare.None修改为FileShare.Read降低冲突概率
  • 之前运行的程序异常退出后残留了未释放的文件句柄,可重启相关进程或开发环境清理残留句柄
  • 输入的urls列表存在重复值,多个任务下载同一个url写入相同路径(如果你的逻辑允许重复url,建议给文件名增加随机后缀区分)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 09:57:04