如何在C#*中创建一个目录*如果它还不存在?

时间:2017-05-18 14:33:23

标签: c# windows io

Directory.CreateDirectory创建一个文件夹(如果该文件夹尚不存在),否则它只返回已存在文件夹的DirectoryInfo。

但是我想确保每次运行进程(run1,run2,run3等)时都创建一个新的子文件夹。多个人可能会立即运行该流程。所以我做不到

if (!Directory.exists("run77"){CreateDirectory("run77");}

因为它有竞争条件 - 其他人可能会在这两个电话之间创建文件夹。

有没有办法确保我肯定会获得下一个未使用的文件夹名称?

4 个答案:

答案 0 :(得分:3)

显而易见的答案:在这种情况下不要使用顺序ID。请改用GUID。对于同时在多个实例中发生的事情,我很少发现序列号有用,因为实际上没有固有的序列

另一个选项是下拉到the Windows API,您可以尝试重新尝试创建具有递增序列号的目录,直到调用成功,此时您找到了可以使用的目录。

答案 1 :(得分:2)

这不仅仅是创建目录。您有多个进程(甚至可能在多台计算机上),这些进程只能为自己获取顺序命名的资源。

如果你肯定想要这样做,你必须自己同步。所以:

  • 如果进程在同一台计算机上运行,​​请使用同步目录创建代码的计算机范围的锁(例如Mutex)。
  • 创建一个进程外中央权限(文件系统本身除外),在每次连续同步调用时提供下一个数字。
  • 创建一个包含特定于进程的值的sentinel文件/锁定文件,在此期间没有其他进程尝试创建目录,并在创建目录后将其删除。
  • 以这种方式应用文件系统权限,尝试写入给定目录会引发错误(如果CreateDirectory()没有抛出)。然后你必须假设任何权限错误意味着发生竞争条件,并尝试创建下一个目录。

所有这些都是脆弱的解决方案。

答案 2 :(得分:1)

一种可能的解决方案是使用专门打开的文件引入简单同步。

这是可能的实现(因为没有完全想到的代码):

FileStream lock = null;
try
{
    // someUniequeLockFileName - should be the same for all processes and unlikely to match real name in that folder
    lock = File.Open(Path.Combine(currentFolder, someUniqueLockFileName), FileMode.Create, FileAccess.ReadWrite, FileShare.None);
    ... // you successfully obtain lock, can create subfolders
}
catch { }
finally
{
    lock.Close();
}

答案 3 :(得分:1)

一种方法是使用mutex这是一个昂贵的电话。但是,如果可能的话,大多数人都会使用顺序ID代替。以下是使用mutex

的示例
Mutex m = null
try
{
    m = new Mutex(false, "CreateDirectoryMutex");
    m.WaitOne();
    if (!Directory.exists("run77"))
        CreateDirectory("run77");
}
finally
{
     if(m != null)
       m.ReleaseMutex();
 }