C# 文件移动和覆盖
我正在开发一个多线程应用程序。我的代码中有一处:
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 文件,但那个线程只读取该文件,没有写入操作。我使用锁来保护竞争条件。不知道为什么会发生这种情况。
更新:即使 Visual C# 调试器向我显示此异常,查看包含这些文件的目录,我发现没有 sidetapedata.txt
文件,但有一个 sidetapedata2.txt
文件!
UPDATE2:此外,仅当 sidetapedata.txt
和 sidetapedata2.txt
均为空白时才会发生此行为
I'm developing a multi threaded application. I have somewhere in my code :
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.
The second line sometimes runs fine and other times, it throws an IOException
:
Cannot create a file when that file already exists.
There is one more thread that is accessing the sidetapedata
file but that one is only reading this file, no write operations. I am using locks to protect race conditions. Don't know why this is happening.
UPDATE : even when visual c# debugger shows me this exception, looking into the directory that contains these files, I see there is no sidetapedata.txt
file but there is a sidetapedata2.txt
file!
UPDATE2 : Also, this behavior only happens when sidetapedata.txt
and sidetapedata2.txt
are both blank
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不知道为什么会发生这种情况,除非
Delete
调用在文件系统中触发了某些事件,这意味着直到调用返回后不久,它才实际上被删除。有几个选项:File.Move
而不是File.Delete
将其移动到某个无害的其他文件名,然后将其删除,希望Move
比Delete
更原子。我怀疑线程在这里无关紧要 - 我建议您编写一个简短但完整的程序来验证这一点,以便您可以排除它(并轻松测试解决方法)。
Not sure why this would happen unless there's some event triggered in the file system by the
Delete
call which means it's not actually deleted until slightly after the call returns. A few options:File.Copy(sidetapedata, sidetapedata2, true)
to copy instead of moving, and then delete the source file. This will be less efficient though, assuming the move would be handled by a simple file system directory entry change (rather than really copying the data)File.Move
on the target file instead ofFile.Delete
to move it to some harmless other filename, then delete that afterwards, hoping that theMove
is more atomic than theDelete
.I suspect the threading is irrelevant here - I suggest you write a short but complete program to validate that, so you can rule it out (and easily test the workarounds).
我不确定这对于 .NET 是否相同,但根据 win32 DeleteFile API参考:
因此,在调用Delete 返回和Windows 关闭文件的最后一个句柄之间可能存在一个时间窗口。看来你是在这段时间打电话给Move的。
I am unsure if this is the same for .NET, but according to the win32 DeleteFile api reference:
So there is probably a window of time between the call to Delete returning and Windows closing the last handle to the file. It looks like you are calling Move during this period of time.
在.NET Core 3.0及更高版本中,您可以调用Move(String, String, Boolean)并将参数overwrite设置为true,这将替换文件(如果存在)。
请参阅 https://learn .microsoft.com/en-us/dotnet/api/system.io.file.move?view=netcore-3.0
In .NET Core 3.0 and later versions, you can call Move(String, String, Boolean) setting the parameter overwrite to true, which will replace the file if it exists.
see https://learn.microsoft.com/en-us/dotnet/api/system.io.file.move?view=netcore-3.0
根据这个答案:使用FileStream 与 文件共享
As per this answer : use FileStream with FileShare