.NET開発者のためのブログメディア
C#のMutexとは?2つの種類と使用方法を理解しよう!

- SE
- Mutexとは、どのようなものなのでしょうか?
- PM
- MUTual EXclusionの略で「相互排除」という意味です。この記事で、詳しくみていきましょう。
目次
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を使うのも良いでしょう。
- SE
- 排他制御したり、多重起動を禁止したりできるのですね。
- PM
- アプリケーションを1度に1つしか起動されたくない場合などに、Mutexを使用します。興味深いですね。
C#のMutexを活用しよう!
C#のMutexには、「名前付きMutex」と「名前なしMutex」の2種類があり、その使い方についてご紹介しました。排他制御のために、ぜひMutexを活用してみてください。
ご自身でC#のソースコードを書いて、理解を深めてみてはいかがでしょうか。
Search キーワード検索
Popular 人気の記事
reccomended おすすめ記事
Categories 連載一覧
Tags タグ一覧
Jobs 新着案件
-
開発エンジニア/東京都品川区/【WEB面談可】/在宅ワーク
月給29万~30万円東京都品川区(大崎駅) -
遠隔テストサービス機能改修/JavaScript/東京都港区/【WEB面談可】/テレワーク
月給45万~60万円東京都港区(六本木駅) -
病院内システムの不具合対応、保守/東京都豊島区/【WEB面談可】/テレワーク
月給30万~30万円東京都豊島区(池袋駅) -
開発/JavaScript/東京都豊島区/【WEB面談可】/テレワーク
月給50万~50万円東京都豊島区(大塚駅) -
債権債務システム追加開発/東京都文京区/【WEB面談可】/在宅勤務
月給62万~67万円東京都文京区(後楽園駅)