为何File.Move偶尔失败?目标文件锁/竞态条件/疑似Bug
我在Windows 11机器上运行一段.NET 8的Xunit测试代码时频繁失败,通常在循环变量j处于50-100区间时触发,错误信息为:System.UnauthorizedAccessException: Access to the path is denied.
测试代码1(%TEMP%目录)
[Fact] void FileMoveException() { var sourceFilePath = Path.GetTempFileName(); using var delete1 = Disposable.Create(() => File.Delete(sourceFilePath)); // 可移除,仅用于测试后清理%TEMP%目录 var destFilePath = Path.GetTempFileName(); using var delete2 = Disposable.Create(() => File.Delete(destFilePath)); // 可移除,仅用于测试后清理%TEMP%目录 for(int j = 0; j < 10000; j++) { //try { File.WriteAllText(sourceFilePath, "test"); // File.Delete(destFilePath); // 执行此语句后测试可正常运行 File.Move(sourceFilePath, destFilePath, true); } // catch (Exception e) when (!Debugger.IsAttached) // { // Console.WriteLine($"Failed j={j} {sourceFilePath} {destFilePath} {e}"); // _testOutputHelper.WriteLine($"Failed j={j} {sourceFilePath} {destFilePath} {e}"); // throw; // } } }
问题细节
- 测试在SSD本地文件系统的%TEMP%目录执行,错误触发具有不确定性,每次失败的j值不同
- Windows Defender处于启用状态,但认为其不会改变文件系统行为(仅可能影响性能)
- 若在
File.Move前执行File.Delete(destFilePath),测试可正常运行(已测试100000次循环) - 仅添加
Thread.Sleep(1)或Thread.Sleep(10)无法解决问题,仍会出现相同故障,失败的循环次数也相近 - 经测试问题与源文件无关,疑似目标文件被前一次循环操作锁定
- 使用带
WriteThrough选项的Win32 API函数MoveFileEx也无法解决该问题 - 原本认为同一本地文件夹内的
File.Move是原子操作,或至少函数执行完毕后不会再锁定文件 - 补充:该问题在不同硬件配置的机器上均会出现
测试代码2(非%TEMP%目录)
[Fact] void FileMoveException2() { var sourceFilePath = @"c:\tmp2\source.txt"; var destFilePath = @"c:\tmp2\target.txt"; for (int j = 0; j < 10000; j++) { try { using (var x = new FileStream(sourceFilePath, new FileStreamOptions() { Options = FileOptions.WriteThrough, Access = FileAccess.Write, Mode = FileMode.OpenOrCreate, Share = FileShare.None })) { x.WriteByte(42); } File.Move(sourceFilePath, destFilePath, true); } catch (Exception e) when (!Debugger.IsAttached) { Console.WriteLine($"Failed j={j} {sourceFilePath} {destFilePath} {e}"); _testOutputHelper.WriteLine($"Failed j={j} {sourceFilePath} {destFilePath} {e}"); throw; } } }
内容的提问来源于stack exchange,提问作者stb
相关产品推荐
相关产品推荐

