Ответ 1
Вы можете использовать класс System.Threading.Mutex, который имеет метод OpenExisting для открытия именованного системного мьютекса.
Это не отвечает на вопрос:
Как создать системный/многопроцессорный Mutex
Чтобы создать общесистемный мьютекс, вызовите конструктор System.Threading.Mutex, который принимает строку в качестве аргумента. Это также известно как "именованный" мьютекс. Чтобы убедиться, что он существует, я не могу найти более грациозный метод, чем try catch:
System.Threading.Mutex _mutey = null;
try
{
_mutey = System.Threading.Mutex.OpenExisting("mutex_name");
//we got Mutey and can try to obtain a lock by waitone
_mutey.WaitOne();
}
catch
{
//the specified mutex doesn't exist, we should create it
_mutey = new System.Threading.Mutex("mutex_name"); //these names need to match.
}
Теперь, чтобы быть хорошим программистом, вам нужно, когда вы закончите программу, отпустить этот мьютекс
_mutey.ReleaseMutex();
или вы можете оставить его, и в этом случае он будет называться "оставленным", когда ваш поток выйдет, и разрешит другому процессу его создать.
[EDIT]
В качестве побочного примечания к последнему предложению, описывающему мьютекс, который оставлен, когда другой поток получает мьютекс, исключение System.Threading.AbandonedMutexException
будет передано ему, если оно обнаружено в заброшенном состоянии.
[EDIT TWO]
Я не уверен, почему я ответил на этот вопрос много лет назад; существует (и была) перегрузка конструктора, что намного лучше проверяет существующий мьютекс. Фактически, код, который я дал, кажется, имеет состояние гонки! (И позор вам всех за то, что я не исправил меня!: -P)
Здесь условие гонки: Представьте себе два процесса, оба они одновременно пытаются открыть существующий мьютекс, и оба попадают в секцию catch кода. Затем один из процессов создает мьютекс и живет долго и счастливо. Другой процесс, однако, пытается создать мьютекс, но на этот раз он уже создан! Эта проверка/создание мьютекса должна быть атомарной.
http://msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.90).aspx
Итак...
var requestInitialOwnership = false;
bool mutexWasCreated;
Mutex m = new Mutex(requestInitialOwnership,
"MyMutex", out mutexWasCreated);
Я думаю, что здесь трюк заключается в том, что кажется, что у вас есть вариант, который у вас на самом деле нет (выглядит как недостаток дизайна для меня). Иногда вы не можете определить, есть ли у вас мьютекс, если вы отправляете true
для requestInitialOwnership
. Если вы передадите true
, и кажется, что ваш вызов создал мьютекс, то, очевидно, вы его обладаете (подтверждено документацией). Если вы передадите true
, и ваш вызов не создал мьютекс, все, что вы знаете, это то, что мьютекс уже создан, вы не знаете, принадлежит ли какой-либо другой процесс или поток, который, возможно, создал мьютекс, в настоящее время принадлежит мьютекс. Итак, вы должны WaitOne
убедиться, что у вас есть это. Но тогда, сколько Release
вы делаете? Если какой-либо другой процесс имел мьютекс, когда вы его получили, то только ваш явный вызов WaitOne
должен быть Release
d. Если ваш вызов конструктору заставил вас использовать мьютекс и вы явно вызвали WaitOne
, вам понадобятся два Release
s.
Я вложу эти слова в код:
var requestInitialOwnership = true; /*This appears to be a mistake.*/
bool mutexWasCreated;
Mutex m = new Mutex(requestInitialOwnership,
"MyMutex", out mutexWasCreated);
if ( !mutexWasCreated )
{
bool calledWaitOne = false;
if ( ! iOwnMutex(m) ) /*I don't know of a method like this*/
{
calledWaitOne = true;
m.WaitOne();
}
doWorkWhileHoldingMutex();
m.Release();
if ( calledWaitOne )
{
m.Release();
}
}
Поскольку я не вижу способа проверить, принадлежит ли вам мьютекст, я настоятельно рекомендую вам передать false
конструктору, чтобы вы знали, что вы не являетесь владельцем мьютекса, и знаете, как много раз для вызова Release
.