Search code examples
c#wpfsystem.io.filesystem.io.directory

Creating (N) directories in a specific path in a loop stopping abruptly


I am attempting to create 10,000 folders in a specific directory. I have an algorithm for creating a random names for each folder.

The issue I am having is when I run this code, It stops with creating about 21 directories. The MessageBox.Show() is debug, however, it never pops up.

this.WorkingDir is a string property that looks like this.

"C:\\Users\\Reapism\\Desktop\\Yo\\"

        DirectoryInfo directoryInfo;
        string dirName; // directory name
        const int dirNameLength = 15;

        for (int i = 0; i < 10000; i++) {
            dirName = GetRandomString(dirNameLength); // generates "unique name"
            try {
                directoryInfo = Directory.CreateDirectory(this.WorkingDir + dirName);
            } catch (Exception e) {
                MessageBox.Show($"{i} {dirName} failed. {e.ToString()}");
            }
        }

        // Inserting a breakpoint here yields 21 directories

        DirectoryInfo d = new DirectoryInfo(this.WorkingDir);
        DirectoryInfo[] directories = d.GetDirectories($"*");

        foreach (DirectoryInfo dir in directories) {
            try {
                Directory.Delete(dir.FullName);
            } catch (Exception e) {
                throw new FileNotFoundException($"Error deleting the directory!" + e.ToString());
            }
        }

The interesting thing is when I use the Debugger, and step through each iteration of the for loop in creating the directories, it goes further than 21 directories, and likely goes all the way to 10k. This would lead me to believe there is a limit to creating directories in a certain number of time.

Whats troubling is that no exception is thrown, the loop just discontinues.

Does this have to do with the CPU working quicker than the Disk can report or write a new Folder? If so, how can I get around this? This function is a timed function and using a Thread.Sleep(50) for example cannot be used.


Solution

  • Your function GetRandomString generates non unique names, because you create new Random every times. You can use private class member Random which been created one times with class instance. I wrote sample counting unique names.

    string[] dirNames = new string[10000];
    
    for (i = 0; i < 10000; ++i)
        dirNames[i] = GetRandomString(dirNameLength); // generates "unique name";
    
    foreach (var dr in dirNames.GroupBy(x => x).Select(x => new { Name = x.Key, Count = x.Count() }).Where(x => x.Count > 1))
    {
        Console.WriteLine($"{dr.Count} {dr.Name}");
    }
    

    Try this. Аnd don't forget that filenames are case insensitive, so you should use only 36 characters, not 62.

    private static readonly char[] charList = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();
    private static readonly Random _random = new Random();
    
    private static string GetRandomString(int length)
    {
        if (length < 1)
            throw new ArgumentOutOfRangeException("Length must be greater than 0!");
    
        return new string(Enumerable.Repeat(charList, length).Select(s => s[_random.Next(s.Length)]).ToArray());
    }