Reputation: 6627
I'm trying to work out when is the right time to use ReleaseMutex
, and when is the right time to use Close
.
We are (effectively) writing an "auto-updater" type application in C#. The user can run more than one instance of the auto-updater at the same time, however each one must wait for other instances to finish before it proceeds. So effectively, the application flow is as follows:
new Mutex(false, "MyMutex", out isCreator)
)Mutex.WaitOne
)
It's that final step that I'm wondering about. If a particular application instance created the Mutex, then I figured it would be safe for that instance to also close the Mutex; but, I'm not sure what this would do to other application instances that are then waiting on that Mutex.
A safer option seems to be to let each application simply release the mutex; however, I don't know in this case if the mutex would ever be destroyed?
private const string _mutexName = "NinjaMutexAwesomePants";
private static int _threadId;
void Main()
{
Task.Factory.StartNew(AcquireMutex);
Task.Factory.StartNew(AcquireMutex);
Task.Factory.StartNew(AcquireMutex);
}
void Trace(int threadId, string text, params object[] args)
{
var trace = String.Concat(
String.Format("{0:hh:mm:ss.ffff} T{1}: ", DateTime.Now, threadId),
String.Format(text, args));
Console.WriteLine(trace);
}
void AcquireMutex()
{
var threadId = Interlocked.Increment(ref _threadId);
Trace(threadId, "Started!");
bool createdNew;
var mutex = new Mutex(false, _mutexName, out createdNew);
if (createdNew)
Trace(threadId, "I am the creator!");
else
Trace(threadId, "I did not create the mutex.");
try
{
var isOwner = mutex.WaitOne(TimeSpan.FromSeconds(5));
if (isOwner)
Trace(threadId, "I am the owner of the mutex!");
else
Trace(threadId, "I couldn't acquire the mutex.");
if (isOwner)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
if (createdNew)
mutex.Close();
else
mutex.ReleaseMutex();
Trace(threadId, "I have released the mutex.");
}
}
catch (Exception ex)
{
Trace(threadId, "{0}: {1}", ex.GetType().Name, ex.Message);
}
}
However, this didn't really clear things up for me. Seemingly, always using ReleaseMutex
is the safest option (instead of calling Close
), however this also seems like the mutex is never closed even after all threads have released the mutex. In fact, in the code above - if the creator thread also closes the mutex, the consumer threads can never acquire it.
So, my questions are twofold:
ReleaseMutex
, does the mutex close itself after all threads have released it?Upvotes: 0
Views: 550
Reputation: 4523
I would suggest to implement IDisposable
for this purpose
class Updater : IDisposable
{
private readonly Mutex _mutex;
public Updater(string mutexName)
{
bool createdNew;
_mutex = new Mutex(false, mutexName, out createdNew);
if (!_mutex.WaitOne(TimeSpan.FromSeconds(5)) throw new Exception("I could not acquire mutex");
}
public void Update()
{
// Perform the update
}
public void Dispose()
{
_mutex.ReleaseMutex();
_mutex.Close();
}
}
using (var updater = new Updater("NinjaMutexAwesomePants"))
{
updater.Update();
}
Upvotes: 1