Using Directory.Delete() and Directory.CreateDirectory() to overwrite a folder

后端 未结 3 1753
走了就别回头了
走了就别回头了 2021-01-01 23:29

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

string myDir = \"...\";
if(Directory.Exists(myDir)) 
{
    Dir         


        
3条回答
  •  鱼传尺愫
    2021-01-02 00:12

    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):

    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.

    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.

    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.

    EDIT: 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");                 
            }            
        }        
    }
    

    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.

    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();
            }
        }        
     }
    

    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.

提交回复
热议问题