Я использую именованный системный мьютекс, чтобы синхронизировать 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
выбрасывается, перед вызовом есть небольшое окно, где другое приложение, возможно, приобрело мьютекс.
Каков наилучший способ избежать этого состояния гонки и сделать этот код более надежным?
Коллега упоминает, что он использовал CreateMutex
из SDK Win32 Platform в своем коде (другой процесс, который необходимо синхронизировать). Однако это, похоже, не поддерживается в основном .NET Framework. Поэтому я не уверен, что это лучшее решение для моего кода.
Update
На основании ответа от @David Шварца, вот мой новый код:
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;
}
Да, это не сработает. Вам нужно сделать один из процессов босса, тот, который его создает. Выберите один, как правило, первый. Если другой процесс не может открыть его, значит, что-то действительно не так. Он должен ждать. –
@ Ханс - Я вносил изменения, основанные на ответе Дэвида Шварца: можете ли вы увидеть мой обновленный код и сообщить мне, если он выглядит правильно. – LeopardSkinPillBoxHat
AbandonedMutexException вызывается только в том случае, если вы делаете что-то серьезно неправильно. Я бы не замолчил его, как в коде выше, но позвольте моему глобальному обработчику исключений зарегистрировать его для дальнейшего анализа. См. Https://msdn.microsoft.com/en-us/library/system.threading.abandonedmutexexception(v=vs.110).aspx –