Reputation: 5490
Directory.CreateDirectory creates a folder if it doesn't already exist, otherwise it just returns the DirectoryInfo for the already-existing folder.
But I want to make sure I create a new sub-folder every time a process is run (run1, run2, run3, etc). And multiple people may be running that process at once. So I can't do
if (!Directory.exists("run77"){CreateDirectory("run77");}
Because that has a race condition - someone else may create the folder in between those two calls.
Is there any way to ensure that I definitely get the next unused folder name?
Upvotes: 1
Views: 856
Reputation: 1849
One way is using a mutex
which is an expensive call. However like most said if possible use sequential Ids instead. Here is an example using a mutex
:
Mutex m = null
try
{
m = new Mutex(false, "CreateDirectoryMutex");
m.WaitOne();
if (!Directory.exists("run77"))
CreateDirectory("run77");
}
finally
{
if(m != null)
m.ReleaseMutex();
}
Upvotes: 1
Reputation: 354476
The obvious answer: Don't use sequential IDs in this case. Use GUIDs instead. For things happening in multiple instances at once I rarely found sequential numbers helpful in that there isn't really an inherent sequence.
The other option would be to drop down to the Windows API where you can just try and re-try creating directories with increasing sequence numbers until the call succeeds, at which point you found your directory to work with.
Upvotes: 3
Reputation: 21999
One possible solution is to introduce a simple synchronization using exclusively opened file.
Here is possible implementation (as not fully thought code):
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();
}
Upvotes: 1
Reputation: 151584
This goes way beyond merely creating directories. You have multiple processes (on multiple machines even, maybe) that want to obtain a sequentially named resources, for themselves only.
If you definitely want to do this, you will have to synchronize it yourself. So either:
CreateDirectory()
doesn't throw already). Then you'll have to assume that any permission error means a race condition occurred, and try to create the next directory.All of those are brittle solutions.
Upvotes: 2