我尝试在适当的时候使用ReleaseMutex
,以及何时适合使用Close
。
我们(有效地)正在编写一个"自动更新程序"在C#中键入应用程序。用户可以同时运行自动更新程序的多个实例,但是每个实例必须等待其他实例在完成之前完成。如此有效,申请流程如下:
new Mutex(false, "MyMutex", out isCreator)
)Mutex.WaitOne
)
这是我想知道的最后一步。如果特定的应用程序实例创建了 Mutex,那么我认为该实例也可以安全地关闭 Mutex;但是,我不确定这会对那些等待该Mutex的其他应用程序实例做些什么。
更安全的选择似乎是让每个应用程序只需释放互斥锁;但是,在这种情况下,我不知道互斥锁是否会被破坏?
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);
}
}
但是,这对我来说并不是很清楚。看起来,总是使用ReleaseMutex
是最安全的选择(而不是调用Close
),但是,即使所有线程都释放了互斥锁,这似乎也永远不会关闭互斥锁。实际上,在上面的代码中 - 如果创建者线程也关闭了互斥锁,则消费者线程永远无法获取它。
所以,我的问题有两个:
ReleaseMutex
,那么在所有线程释放后,互斥锁是否会自行关闭?答案 0 :(得分:1)
我建议为此目的实施IDisposable
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();
}