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
相关产品推荐
相关产品推荐

