Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#文件移动和覆盖_C#_Multithreading_Race Condition_Ioexception - Fatal编程技术网

c#文件移动和覆盖

c#文件移动和覆盖,c#,multithreading,race-condition,ioexception,C#,Multithreading,Race Condition,Ioexception,我正在开发一个多线程应用程序。我的代码中有: 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: 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
文件,但该线程只读取此文件,没有写入操作。Iam使用锁来保护竞争条件。我不知道为什么会这样

更新:即使visual c#debugger向我显示此异常,查看包含这些文件的目录时,我发现没有
sidetapedata.txt
文件,但有一个
sidetapedata2.txt
文件


UPDATE2:此外,只有当
sidetapedata.txt
sidetapedata2.txt
都为空时才会发生这种行为,不确定为什么会发生这种情况,除非文件系统中有某个事件由
Delete
调用触发,这意味着只有在调用返回后才会真正删除它。有几个选择:

  • 您可以在尝试移动之前检查文件是否存在的位置进行循环(出错前循环的最大数量),如果删除后文件仍然存在,则短暂休眠
  • 您可以使用
    File.Copy(sidetapedata,sidetapedata2,true)
    复制而不是移动,然后删除源文件。但是,如果通过简单的文件系统目录条目更改(而不是真正复制数据)来处理移动,则效率会降低
  • 您可以在目标文件上使用
    File.Move
    ,而不是
    File.Delete
    将其移动到其他无害的文件名,然后将其删除,希望
    Move
    Delete
    更原子化

我怀疑线程与此无关-我建议您编写一个简短但完整的程序来验证这一点,这样您就可以排除它(并轻松测试解决方法)。

我不确定这是否与.NET相同,但根据win32 api参考:

DeleteFile函数在关闭时标记要删除的文件。因此,在关闭文件的最后一个句柄之前,不会删除文件

因此,在调用Delete返回和Windows关闭文件的最后一个句柄之间可能有一段时间。在这段时间内,您似乎正在调用Move。

根据此:与一起使用


在.NET Core 3.0及更高版本中,您可以调用Move(String、String、Boolean)将参数overwrite设置为true,如果文件存在,将替换该文件


请参见

删除前重命名文件,Windows/antivirus/etc有时会在您要求Windows删除文件后的几分钟内使文件“存在”。不是说您的答案需要验证,而是说您使用线程是正确的。删除后请短暂睡眠,这为我解决了单线程应用程序中的类似问题。干杯
FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.None);