Azure WebJob中Stream.CopyTo执行时文件被锁定问题求助
队列触发WebJob大文件下载锁冲突问题解决
可能的触发原因
- Windows App Service默认启用的Antimalware扫描进程会在文件创建后立即扫描,大文件写入过程中被扫描进程锁定。
FileShare.None的严格权限设置完全禁止其他进程访问,哪怕是系统服务也会触发冲突。- 队列触发的WebJob存在并发实例,多个进程同时尝试操作同一个目标文件。
- Azure App Service的网络挂载存储(如D:\home)存在文件锁释放延迟,导致后续操作误以为文件仍被占用。
具体解决方案
1. 改用临时文件+原子重命名(优先推荐)
先将文件写入临时路径,完成后再重命名到目标位置,这是避免中间状态锁冲突的原子操作:
ShareFileClient file = shareDir.GetFileClient($"{list}.dat"); if (!file.Exists()) { logger.LogError($"ERROR: Couldn't find {list}.dat file in the file share."); return; } try { string tempFilePath = Path.Combine(downloadPath, $"{list}.tmp"); ShareFileDownloadInfo download = file.Download(); using (FileStream fs = new FileStream(tempFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) { download.Content.CopyTo(fs); } // 重命名操作是原子性的,避免扫描进程锁定中间状态的文件 File.Move(tempFilePath, Path.Combine(downloadPath, $"{list}.dat"), overwrite: true); } catch (Exception ex) { logger.LogError($"EXCEPTION: An exception occurred while downloading {list}.dat.{Environment.NewLine}{ex.Message}{Environment.NewLine}{ex.InnerException?.Message ?? ""}"); // 清理临时文件 string tempFilePath = Path.Combine(downloadPath, $"{list}.tmp"); if (File.Exists(tempFilePath)) File.Delete(tempFilePath); return; }
2. 调整FileStream共享权限
将FileShare.None改为FileShare.Read,允许系统扫描进程读取文件,避免锁冲突:
using (FileStream fs = new FileStream(Path.Combine(downloadPath, $"{list}.dat"), FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { download.Content.CopyTo(fs); }
3. 控制WebJob并发
如果是多实例并发导致的冲突,在WebJob根目录创建settings.job文件,强制单实例运行:
{ "is_singleton": true }
或者使用Azure Blob分布式锁,确保同一时间只有一个进程处理目标文件。
4. 分块写入优化大文件
对于1.5GB的大文件,分块写入可以减少锁持有时间,同时降低内存占用:
using (FileStream fs = new FileStream(Path.Combine(downloadPath, $"{list}.dat"), FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { byte[] buffer = new byte[81920]; // 80KB缓冲区 int bytesRead; while ((bytesRead = download.Content.Read(buffer, 0, buffer.Length)) > 0) { fs.Write(buffer, 0, bytesRead); fs.Flush(); // 及时刷新缓冲区,缩短锁持有时间 } }
5. 临时关闭Antimalware扫描(谨慎使用)
如果确认是杀毒扫描导致的问题,可以在App Service应用设置中添加:
WEBSITE_DISABLE_SCM_SECURITY_SCAN = trueWEBSITE_DISABLE_FTP_SECURITY_SCAN = true
注意:此操作会降低应用安全性,仅在测试或确认无风险场景下使用。
验证建议
- 查看App Service诊断工具的Process Explorer,确认占用文件的进程(通常是MsMpEng.exe,Windows Defender)。
- 检查WebJob运行日志,确认是否存在多实例并发启动的记录。
内容的提问来源于stack exchange,提问作者Disco Globeulon
相关产品推荐
相关产品推荐

