最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Why does File.Move sometimes fail (rare target file lockrace conditionbug)? - Stack Overflow

programmeradmin5浏览0评论

The following .NET 8 targetted code (formatted as xunit test) fails on my machine (Windows 11), typically j is something between 50 and 100.

[Fact]
void FileMoveException()
{
    var sourceFilePath = Path.GetTempFileName();
    using var delete1 = Disposable.Create(() => File.Delete(sourceFilePath)); // can be removed, just helps clean up %TEMP% after the unit test
    var destFilePath = Path.GetTempFileName();
    using var delete2 = Disposable.Create(() => File.Delete(destFilePath)); // can be removed, just helps clean up %TEMP% after the unit test
    
    for(int j = 0; j < 10000; j++)
    {
        //try
        {
            File.WriteAllText(sourceFilePath, "test");
            // File.Delete(destFilePath); // works if File.Delete is executed
            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;
        // }
    }
}

Local file system (%TEMP%) on an SSD drive. Error occurs non-deterministic (different j). Windows defender is active but IMHO should not change FileSystem behaviour (aside from performance of course).

If I File.Delete (see code comment) before File.Move everything seems to work fine (tested with 100000 iterations). If I just add some Thread.Sleep(1) or Thread.Sleep(10) it does not work (same issue, even similar iteration count).

From my experiments it's not related to the source file. Seems like the destination file is (still) blocked by a previous iteration.

Using win32 api function MoveFileEx with WriteThrough option did not help, either.

I thought File.Move would be an atomic operation (operating in same local folder) or at least function should not lock the file beyond runtime.

Edit: Occurs on different machines (different hardware etc).

Edit2: Error is System.UnauthorizedAccessException: Access to the path is denied.

Edit3: Another test without %TEMP% and without Disposable helper and with a variant to create the file:

[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;
        }
    }
}
发布评论

评论列表(0)

  1. 暂无评论