我正在开发一个多线程应用程序。我的代码中有一处:
File.Delete(sidetapedata);
File.Move(sidetapedata2, sidetapedata); //sidetapedata and sidetapedata2 are two file paths that correspond to sidetapedata.txt and sidetaptdata2.txt in some directory.
第二行有时可以正常运行,有时会抛出IOException
:
Cannot create a file when that file already exists.
还有一个线程正在访问sidetapedata
文件,但只有一个只读取此文件,没有写入操作。我我使用锁来保护竞争条件。不知道为什么会这样。
UPDATE :即使visual c#debugger向我显示此异常,查看包含这些文件的目录,我看到没有sidetapedata.txt
文件但是有一个sidetapedata2.txt
文件!
UPDATE2 :此外,仅当sidetapedata.txt
和sidetapedata2.txt
都为空时才会出现此行为
答案 0 :(得分:8)
不确定为什么会发生这种情况,除非Delete
调用在文件系统中触发了某些事件,这意味着在调用返回之后,它不会实际删除。一些选择:
File.Copy(sidetapedata, sidetapedata2, true)
复制而不是移动,然后删除源文件。假设移动将通过简单的文件系统目录条目更改(而不是真正复制数据)来处理,这样效率会降低。File.Move
上使用File.Delete
将其移动到某个无害的其他文件名,然后删除它,希望Move
比Delete
更原子。 {1}}。我怀疑这里的线程无关紧要 - 我建议你写一个简短但完整的程序来验证它,这样你就可以排除它(并轻松测试解决方法)。
答案 1 :(得分:3)
我不确定.NET是否相同,但根据win32 DeleteFile api引用:
DeleteFile函数在关闭时标记要删除的文件。因此,在关闭文件的最后一个句柄之前,不会发生文件删除。
因此,在调用Delete返回和Windows关闭文件的最后一个句柄之间可能存在一个时间窗口。看起来你在这段时间内正在调用Move。
答案 2 :(得分:1)
在 .NET Core 3.0 及以后的版本中,您可以调用 Move(String, String, Boolean) 将参数 overwrite 设置为 true,如果文件存在,它将替换文件。
见https://docs.microsoft.com/en-us/dotnet/api/system.io.file.move?view=netcore-3.0
答案 3 :(得分:0)
根据此answer:将FileStream与FileShare
一起使用FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None);