Azure环境启动StreamWriter时抛出文件被占用异常如何解决?
异常原因分析
- 固定文件名冲突:始终使用
myFile.csv作为固定文件名,若24小时定时任务出现重叠触发(例如前一次任务执行超时未完成,新的定时任务已启动),两个进程同时尝试访问同一文件会触发占用异常。 - 异常场景下的句柄残留:如果某次任务执行过程中抛出未捕获的异常,后续的文件删除逻辑未被执行,残留的文件句柄没有被正确释放,下一次任务运行时就会检测到占用。
- Azure运行环境的后台锁定:Azure App Service的站点目录会被平台自带的日志采集、部署扫描等后台操作短时间锁定,若和你的写文件时机重合也会触发该报错。
解决方法
- 生成唯一文件名避免冲突
不要使用固定文件名,可拼接时间戳、GUID生成唯一的临时文件名,从根源上避免多进程访问同一文件的问题,示例代码:
// 拼接时间戳和短GUID生成唯一文件名 string fileName = $"myFile_{DateTime.Now:yyyyMMddHHmmss}_{Guid.NewGuid().ToString("N")[..6]}.csv"; string filePath = Path.Combine(Environment.CurrentDirectory, fileName);
- 增加文件占用重试逻辑
捕捉IO异常后增加重试机制,遇到短时间的文件锁定可以等待后重试,避免单次失败就抛出异常:
int maxRetryCount = 3; for (int i = 0; i < maxRetryCount; i++) { try { using (var w = new StreamWriter(filePath, false, new UTF8Encoding(false))) { // 原有业务代码 } break; } catch (IOException) { if (i == maxRetryCount - 1) throw; Thread.Sleep(1000); // 等待1秒后重试 } }
- 改用临时目录存储临时文件
不要将临时文件放在站点根目录wwwroot下,改用系统提供的临时目录,该目录不会被Azure平台的后台扫描操作锁定,路径获取代码:
string tempDir = Path.GetTempPath(); string filePath = Path.Combine(tempDir, fileName);
- 显式指定文件共享权限
创建文件流时显式设置文件共享模式,降低占用冲突概率:
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var w = new StreamWriter(fs, new UTF8Encoding(false))) { // 原有业务代码 }
内容的提问来源于stack exchange,提问作者mnc
相关产品推荐
相关产品推荐

