[System.Security.SecurityCritical] public Mutex ( bool initiallyOwned, // 呼び出し元のスレッドに、初期所有権を与えるならばtrue string name, // Mutexの名前。nullならば無名 out bool createdNew // Mutexが作成されたか否かの結果を得るために渡す値 );Mutex(Boolean, String, Boolean) - Mutex コンストラクター (System.Threading) | Microsoft Learn
引数を省略するとinitiallyOwnedはfalse、nameはnull、そしてcreatedNewにはダミーの値が渡されます。Mutex - mutex.cs
initiallyOwnedをtrueとすると、コンストラクタを呼び出したスレッド以外からはシグナルを得られなくなります。
Mutex mutex = new Mutex(true); Task.Run(() => { bool r1 = mutex.WaitOne(0); // false (スレッドが異なるため、シグナルを得られない) }).Wait(); bool r2 = mutex.WaitOne(0); // true
Mutex mutex = new Mutex(false); Task.Run(() => { bool r1 = mutex.WaitOne(0); // true (スレッドが異なるが、シグナルを得られる) mutex.ReleaseMutex(); }).Wait(); bool r3 = mutex.WaitOne(0); // true
Mutex mutex = null; Task.Run(() => { mutex = new Mutex(true); // コンストラクタの呼び出し bool r1 = mutex.WaitOne(0); // true mutex.ReleaseMutex(); }).Wait(); bool r2 = mutex.WaitOne(0); // false (スレッドが異なるため、シグナルを得られない)
MutexはWaitHandleクラスを継承するため、そのメソッドを利用できます。
Mutexを一度解放できます。
public void ReleaseMutex ();Mutex.ReleaseMutex メソッド (System.Threading) | Microsoft Learn
シグナルを受け取ったスレッド以外でMutexを解放すると、「オブジェクト同期メソッドは、コードの非同期ブロックから呼び出されました。」としてApplicationExceptionが投げられます。
Mutex mutex = new Mutex(false); mutex.WaitOne(); mutex.ReleaseMutex(); // ok mutex.WaitOne(); Task.Run(() => { mutex.ReleaseMutex(); // ApplicationException }).Wait();
bool mutexWasCreated; using (Mutex m = new Mutex(true, "MyMutex", out mutexWasCreated)) { if (mutexWasCreated) { try { // アプリケーションを起動する } finally { m.ReleaseMutex(); } } else { // アプリケーションは、すでに起動している } }
Win32のAPIで可能です。