C#のMutexとは?2つの種類と使用方法を理解しよう!

エンジニア
マネージャー
C#のMutexとは?
今回は、C#のMutexについてご紹介します。Mutexとは、MUTual EXclusionの略で「相互排除」という意味です。排他制御のための仕組みで、対象が「未使用(使用できる)」か「使用中(使用できない)」かを表すものです。
アプリケーションを1度に1つしか起動されたくない場合などに、Mutexを使用します。C#のMutexに興味のある方はぜひご覧ください。
Mutexの種類
C#のMutexには、「名前付きシステムMutex」と「名前のないローカルMutex」の2種類があります。
名前付きでMutexインスタンスを生成すると、オペレーティングシステム全体から参照でき、プロセス間で共有できるシステムMutexとなります。これはアプリケーションの多重起動を禁止するために使用します。
名前なしでMutexインスタンスを生成すると、プロセス内でのみ参照できるローカルMutexとなります。これはアプリケーション内で排他制御する場合に使用します。
以下でC#の「名前付きシステムMutex」と「名前のないローカルMutex」を紹介します。
名前付きMutex
C#の名前付きMutexを使用して、アプリケーションの多重起動を禁止できます。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
using System; using System.Windows.Forms; using System.Threading; namespace WindowsFormsApp1 { static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { // Mutex名(アプリケーション固有の名前) string mutexName = "MySampleApplication"; // Mutexの初期所有権が呼び出し元のスレッドに付与されたかどうかを示すbool値 bool createdNew; // Mutexオブジェクトを作成する Mutex mutex = new Mutex(true, mutexName, out createdNew); // Mutexの初期所有権が付与されたかどうか if (!createdNew) { // Mutexの初期所有権が付与されなかった場合は、多重起動と判断して終了する MessageBox.Show("すでに起動しています。2つ以上同時に起動できません。"); // Mutexを解放する mutex.Close(); return; } try { // Formを起動する Form form = new Form(); Application.Run(form); } finally { // Mutexを解放する mutex.ReleaseMutex(); mutex.Close(); } } } } |
ビルド結果が出力されるフォルダに出力されたexeファイルを起動してみましょう。Fromが表示されます。この状態で、さらにexeファイルを起動してみます。
そうすると、「すでに起動しています。2つ以上同時に起動できません。」というMessageBoxが表示されます。
このように、Mutexを使用して、アプリケーションの多重起動を禁止できます。
名前付きMutex(WaitOne)
名前付きMutexを使用した、もうひとつの方法を紹介します。
WaitOneメソッドを使用します。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
using System; using System.Windows.Forms; using System.Threading; namespace WindowsFormsApp1 { static class Program { /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { // Mutex名(アプリケーション固有の名前) string mutexName = "MySampleApplication"; // Mutexを作成する Mutex mutex = new Mutex(false, mutexName); bool isCreated = false; try { try { // 現在のWaitHandleがシグナルを受信するまで現在のスレッドをブロックする isCreated = mutex.WaitOne(0, false); } // 別のアプリケーションがMutexを解放しないで終了した場合に発生する catch (AbandonedMutexException) { // この場合は起動させる isCreated = true; } // Mutexを得られたか調べる if (!isCreated) { // Mutexの初期所有権が付与されなかった場合は、多重起動と判断して終了する MessageBox.Show("すでに起動しています。2つ以上同時に起動できません。"); return; } // Formを起動する Form form = new Form(); Application.Run(form); } finally { if (isCreated) { //Mutexを解放する mutex.ReleaseMutex(); } mutex.Close(); } } } } |
WaitOneメソッドの書式は、「Mutex.WaitOne(待ち合わせ時間, bool)」です。
第1引数の待ち合わせは、何ミリ秒Mutexの所有権が付与させるのを待つかを指定します。”0″であれば全く待たないということです。
第2引数のbool値は、後で再び所有権を取得する場合はTrue、それ以外の場合はFalseに設定します。
名前なしMutex
C#の名前なしMutexインスタンスを生成すると、プロセス内でのみ排他制御できます。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
using System; using System.Threading; namespace WindowsFormsApp1 { static class Program { public static Mutex mutex = new Mutex(); /// <summary> /// アプリケーションのメイン エントリ ポイントです。 /// </summary> [STAThread] static void Main() { for (int i = 0; i < 10; i++) { (new Thread(new ThreadStart(ThreadFunc))).Start(); } } private static void ThreadFunc() { try { // threadIDの取得 int id = Thread.CurrentThread.ManagedThreadId; // 現在のWaitHandleがシグナルを受信するまで現在のスレッドをブロックする mutex.WaitOne(); Console.WriteLine("thread開始 treadID[" + id + "]"); // 何かの処理 Thread.Sleep(100); Console.WriteLine("thread終了 treadID[" + id + "]"); } finally { // Mutexロック解放 mutex.ReleaseMutex(); } } } } |
実行結果は以下のようになります。
threadIDは環境によって異なります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
thread開始 treadID[4] thread終了 treadID[4] thread開始 treadID[10] thread終了 treadID[10] thread開始 treadID[12] thread終了 treadID[12] thread開始 treadID[11] thread終了 treadID[11] thread開始 treadID[9] thread終了 treadID[9] thread開始 treadID[8] thread終了 treadID[8] thread開始 treadID[6] thread終了 treadID[6] thread開始 treadID[7] thread終了 treadID[7] thread開始 treadID[5] thread終了 treadID[5] thread開始 treadID[3] thread終了 treadID[3] |
スレッドの処理が排他されていることが分かります。
Mutexの解放漏れ
C#に限らず、Mutexを解放しないと、リソースリークが発生します。
予期せぬ場所でアプリケーションが異常終了することもありますので、try-finallyで確実に解放するようにしましょう。
以下は、リソースリークが発生する悪い例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
private static void ThreadFunc() { // threadIDの取得 int id = Thread.CurrentThread.ManagedThreadId; // 現在のWaitHandleがシグナルを受信するまで現在のスレッドをブロックする mutex.WaitOne(); Console.WriteLine("thread開始 treadID[" + id + "]"); // 何かの処理。ここでアプリケーション例外が発生すると、Mutexが解放されない! Thread.Sleep(100); Console.WriteLine("thread終了 treadID[" + id + "]"); // Mutexロック解放 mutex.ReleaseMutex(); } |
C#では、try-finallyで解放するのではなく、usingを使うのも良いでしょう。
エンジニア
マネージャー
C#のMutexを活用しよう!
C#のMutexには、「名前付きMutex」と「名前なしMutex」の2種類があり、その使い方についてご紹介しました。排他制御のために、ぜひMutexを活用してみてください。
ご自身でC#のソースコードを書いて、理解を深めてみてはいかがでしょうか。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


C#新着案件New Job
システム開発/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(新宿駅)システム開発/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(新宿駅)デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円神奈川県横浜市(桜木町駅)デバック、テスト項目の作成/神奈川県横浜市/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円神奈川県横浜市(桜木町駅)基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代前半の方活躍中/経験1年以上の方活躍中】/在宅勤務
月給29万~34万円東京都新宿区(西新宿駅)基幹システム開発導入/東京都新宿区/【WEB面談可/C#経験者/20代後半~40代の方活躍中/経験年数不問】/在宅勤務
月給41万~50万円東京都新宿区(西新宿駅)