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

为何File.Move偶尔失败?目标文件锁/竞态条件/疑似Bug

.NET 8下File.Move重复执行引发UnauthorizedAccessException问题

我在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:55:54