Я использую именованный системный мьютекс для синхронизации 2 процессов.Вот как я сейчас получаю мьютекс в своем приложении:
using System.Threading;
public static bool AcquireMutex()
{
// Protect against double acquisitions
if (MyMutex != null)
{
throw new ApplicationException("Failed to acquire mutex");
}
try
{
// See if a named system mutex has already been created - if it has,
// wait a short amount of time for its release.
MyMutex = Mutex.OpenExisting(MutexName);
if (!MyMutex.WaitOne(TimeSpan.FromSeconds(2), false))
{
// MyMutex still being held
MyMutex = null;
return false;
}
}
catch
{
// MyMutex doesn't exist so create it
MyMutex = new Mutex(true, MutexName);
}
return true;
}
OpenExisting
сгенерирует исключение, если именованный системный мьютекс с MutexName
не существует, что позволяет моему приложению создать его.
Однако, похоже, здесь есть условие гонки - если OpenExisting
бросает, перед вызовом на new Mutex
появляется небольшое окно, где другое приложение могло получить мьютекс.
Каков наилучший способ избежать этого состояния гонки и сделать этот код более надежным?
Коллега упомянул, что он использовал CreateMutex
из Win32 Platform SDK в своем коде (другой процесс, который должен бытьсинхронизированы).Однако эта платформа не поддерживается изначально .NET Framework.Поэтому я не уверен, что это лучшее решение для моего кода.
Обновление
Основываясь на ответе @David Schwartz, вот мой новый код:
public static bool AcquireMutex()
{
// Protect against double acquisitions
if (MyMutex != null)
{
throw new ApplicationException("Failed to acquire mutex");
}
bool createdNew;
MyMutex = new Mutex(true, MutexName, out createdNew);
if (createdNew)
{
// Mutex was created so ownership is guaranteed; no need to wait on it.
return true;
}
try
{
if (!MyMutex.WaitOne(TimeSpan.FromSeconds(2), false))
{
MyMutex = null;
return false;
}
}
catch (AbandonedMutexException)
{
// Other application was aborted, which led to an abandoned mutex.
// This is fine, as we have still successfully acquired the mutex.
}
return true;
}