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

C# .NET复制文件时抛出‘文件正被另一进程使用’异常的问题

解决FileWatcher监控时文件被占用的IOException问题

出现这个异常的核心原因是:FileWatcher的Created事件触发时,文件可能还在被写入它的进程占用——比如上传工具、生成文件的程序还没完成写入就触发了事件,这时候你去打开文件自然会被拒绝。

针对这个问题,你可以从以下几个方面优化代码:

1. 添加带延迟的重试逻辑

当首次访问失败时,等待一小段时间后重试几次,给写入进程足够的时间释放文件锁。

2. 移除冗余的资源释放代码

using语句块会自动调用Dispose()(包含Close()的逻辑),手动调用source.Close()、source.Dispose()完全是多余的,反而可能引发问题。

3. 避免不必要的Task.Run

你的ArchiveFile已经是异步方法,内部不需要再套Task.Run,直接执行异步逻辑即可。

修改后的完整代码

private static async Task ArchiveFile(string filePath)
{
    const int maxRetries = 5;
    const int delayMs = 1000;
    int retryCount = 0;

    while (retryCount < maxRetries)
    {
        try
        {
            var fileName = DateTime.Now.ToString("yyMMdd-HHmmss_") + Path.GetFileName(filePath);
            var archivePath = Path.Combine(StringHelper.ArchivePath, fileName);

            // 使用using自动管理流资源
            using var source = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            using var destination = new FileStream(archivePath, FileMode.Create);

            await source.CopyToAsync(destination);
            Console.WriteLine($"Added file '{fileName}' to archive.");
            return; // 成功归档,退出方法
        }
        catch (IOException e)
        {
            retryCount++;
            if (retryCount >= maxRetries)
            {
                Console.WriteLine($"最终无法访问文件 {filePath}: {e.Message}");
                return;
            }
            Console.WriteLine($"访问文件失败,{delayMs}ms后重试(第{retryCount}次):{e.Message}");
            await Task.Delay(delayMs);
        }
    }
}

额外提示

  • 如果你监控的是大文件,还可以考虑监听FileWatcher的Changed事件(结合文件大小变化判断是否写入完成),但重试机制是更通用的解决方案。
  • FileShare.ReadWrite的设置是正确的,它允许其他进程同时读写该文件,避免因为写入进程还在持有写锁导致你无法读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 21:25:18