使用Directory.Delete()和Directory.CreateDirectory()来覆盖文件夹 [英] Using Directory.Delete() and Directory.CreateDirectory() to overwrite a folder

查看:1415
本文介绍了使用Directory.Delete()和Directory.CreateDirectory()来覆盖文件夹的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的的WebAPI 的操作方法,我想创建/覆写使用该code文件夹:

In my WebApi action method, I want to create/over-write a folder using this code:

string myDir = "...";
if(Directory.Exists(myDir)) 
{
    Directory.Delete(myDir, true);
}
Directory.CreateDirectory(myDir);

// 1 - Check the dir 
Debug.WriteLine("Double check if the Dir is created: " + Directory.Exists(myDir));

// Some other stuff here...

// 2 - Check the dir again
Debug.WriteLine("Check again if the Dir still exists: " + Directory.Exists(myDir));

问题

奇怪的是,有时创建目录之后,该目录不存在!

Strangely, sometimes right after creating the directory, the directory does not exist!

有时检查首次迪尔(其中数字1是)时; Directory.Exist()收益真正,其他时间 。检查第二次(其中,数字2是)的目录时发生同样的情况。

Sometimes when checking the dir for the first time (where the number 1 is); Directory.Exist() returns true, other times false. Same happens when checking the dir for the second time (where the number 2 is).

备注


  • code,这部分没有抛出任何异常。

  • 发布在服务器上的网站时,只可以重现此。 (Windows Server 2008中)

  • 访问同一个文件夹时,会发生。

问题


  • 这是一个并发的问题竞争条件吗?

  • 的WebAPI 或操作系统处理并发?

  • 这是覆盖一个文件夹?
  • 的正确方法
  • 我应该手动锁定文件时,我们有很多的API请求到同一个文件?

  • Is this a concurrency issue race condition?
  • Doesn't WebApi or the Operating System handle the concurrency?
  • Is this the correct way to overwrite a folder?
  • Should I lock files manually when we have many API requests to the same file?

或一般的:


  • 什么是这个奇怪的行为的原因是什么?

更新:


  • 使用的DirectoryInfo 刷新()而不是目录并不能解决这个问题。

  • Using DirectoryInfo and Refresh() instead of Directory does not solve the problem.

只有发生时的的递归的选项的删除的是真正。 (和目录不为空)。

Only happens when the recursive option of Delete is true. (and the directory is not empty).

推荐答案

许多文件系统操作都没有对一些文件系统synchonous(在Windows的情况下, - NTFS)。举个例子 RemoveDirectory 调用(被称为通过在某些点Directory.DeleteDirectory):

Many filesystem operations are not synchonous on some filesystems (in case of windows - NTFS). Take for example RemoveDirectory call (which is called by Directory.DeleteDirectory at some point):

该RemoveDirectory功能,标志着接近上删除一个目录。因此,目录不会被删除,直到最后句柄目录被关闭。

The RemoveDirectory function marks a directory for deletion on close. Therefore, the directory is not removed until the last handle to the directory is closed.

正如你看到的,它不会真正删除目录,直到所有的处理将其关闭,但Directory.DeleteDirectory将完成罚款。你的情况,这也是最有可能这样的并发问题 - 当你执行Directory.Exists目录是不是真的创建。

As you see, it will not really delete directory until all handles to it are closed, but Directory.DeleteDirectory will complete fine. In your case that is also most likely such concurrency problem - directory is not really created while you executing Directory.Exists.

所以,只要定期检查您需要什么,不考虑在.NET中的文件系统调用是同步的。也可以使用FileSystemWatcher的在某些情况下,以避免轮询

So, just periodically check what you need and don't consider filesystem calls in .NET to be synchronous. You can also use FileSystemWatcher in some cases to avoid polling.

编辑:我在想如何重现它,这里是code:

I was thinking how to reproduce it, and here is the code:

internal class Program {
    private static void Main(string[] args) {
        const string path = "G:\\test_dir";
        while (true) {         
            if (Directory.Exists(path))
                Directory.Delete(path);       
            Directory.CreateDirectory(path);   
            if (!Directory.Exists(path))
                throw new Exception("Confirmed");                 
        }            
    }        
}

您看,如果所有文件系统的电话都是同步的(.NET中),这code应该没有问题运行。现在,运行code之前,在创建指定路径空目录(preferrably不要使用SSD为),并与Windows资源管理器打开它。现在运行code。对我来说,无论是罚球确认(这正是再现您的问题),或者抛出的Directory.Delete说,目录不存在(几乎相同的情况下)。它做它的100%的时间我。

You see that if all filesystem calls were synchronous (in .NET), this code should run without problem. Now, before running that code, create empty directory at specified path (preferrably don't use SSD for that) and open it with windows explorer. Now run the code. For me it either throws Confirmed (which exactly reproduces your issue) or throws on Directory.Delete saying that directory does not exist (almost the same case). It does it 100% of the time for me.

下面是我的机器上运行时,另一code证实,的确可以为File.Exists到File.Delete调用后直接返回true:

Here is another code which when running on my machine confirms that it's certainly possible for File.Exists to return true directly after File.Delete call:

internal class Program {
    private static void Main(string[] args) {
        while (true) {
            const string path = @"G:\test_dir\test.txt";
            if (File.Exists(path))
                File.Delete(path);
            if (File.Exists(path))
                throw new Exception("Confirmed");
            File.Create(path).Dispose();
        }
    }        
 }

例外

要做到这一点,我开G:\\ test_dir文件夹,这个code的执行过程中试图打开不断出现和消失test.txt文件。几次尝试后,确认异常被抛出(虽然我没有创建或删除文件,并抛出异常后,它不是文件系统present的话)。所以比赛条件在多种情况是可能的,我的答案是正确的。

To do this, I opened G:\test_dir folder and during execution of this code tried to open constantly appearing and disappearing test.txt file. After couple of tries, Confirmed exception was thrown (while I didn't create or delete that file, and after exception is thrown, it's not present on filesystem already). So race conditions are possible in multiple cases and my answer is correct one.

这篇关于使用Directory.Delete()和Directory.CreateDirectory()来覆盖文件夹的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆