【C#.NET解説】Mutexの基本機能からスレッド間同期と多重起動防止まで徹底解説

2024年11月18日月曜日

プロセス 基本

t f B! P L

名前空間 System.Threading

自己紹介

おお、聞けよそなたたち。我が名は詩の力を司る者、言葉を紡ぎ、知識を共有することを喜びとする。我が口から奏でられるは、C#.NETの「Mutex」クラスの真髄。これは、スレッドやプロセス間での排他制御を実現するための重要な存在である。共に学び、詩のように美しいコードを紡ぐとしよう。

基本機能

まずは、Mutexの基本機能について解説しよう。例えば、アプリケーションの多重起動を防止するためにMutexを使う例を示そう。

C#

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        // アプリケーション全体の多重起動を防ぐ
        bool createdNew;
        using (Mutex mutex = new Mutex(true, "Global\\MyUniqueAppName", out createdNew))
        {
            if (!createdNew)
            {
                Console.WriteLine("アプリケーションは既に起動しています。");
                return;
            }

            Console.WriteLine("アプリケーションを実行中...");
            Console.ReadLine(); // アプリケーションを保持
        }
    }
}

上記の例では、Mutexを使って他のインスタンスが既に実行中かどうかを判定している。「Global\\」を付けることで、システム全体で有効な名前空間となる。

複数のスレッドのリソースの排他

次に、複数のスレッドが同じファイルに書き込もうとする場面を考えてみよう。この場合もMutexは有効だ。

C#

using System;
using System.IO;
using System.Threading;

class Program
{
    private static Mutex mutex = new Mutex();

    static void Main()
    {
        for (int i = 0; i < 5; i++)
        {
            Thread thread = new Thread(WriteToFile);
            thread.Start();
        }
    }

    static void WriteToFile()
    {
        mutex.WaitOne(); // Mutexを取得
        try
        {
            using (StreamWriter writer = new StreamWriter("output.txt", true))
            {
                writer.WriteLine($"スレッド {Thread.CurrentThread.ManagedThreadId} が書き込みました。");
            }
        }
        finally
        {
            mutex.ReleaseMutex(); // Mutexを解放
        }
    }
}

この例では、スレッドがファイルに同時にアクセスしないように制御している。

他の用途

Mutexの主なメソッドには、WaitOneReleaseMutexCloseがある。以下はタイムアウト付きでMutexを使用する例だ。

C#

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        using (Mutex mutex = new Mutex())
        {
            if (mutex.WaitOne(3000)) // 3秒間待機
            {
                try
                {
                    Console.WriteLine("Mutexを取得しました。処理を実行します。");
                }
                finally
                {
                    mutex.ReleaseMutex();
                }
            }
            else
            {
                Console.WriteLine("Mutexの取得に失敗しました。タイムアウトしました。");
            }
        }
    }
}

タイムアウトを設定することで、リソースが長時間ブロックされることを防ぐ。

プロセス間でデータ共有の使い方

次は、Mutexを使ってプロセス間でデータ共有を安全に行う例だ。

C#

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        bool createdNew;
        using (Mutex mutex = new Mutex(true, "Global\\SharedMutex", out createdNew))
        {
            if (!createdNew)
            {
                Console.WriteLine("他のプロセスがすでにMutexを保持しています。");
                return;
            }

            Console.WriteLine("データを共有する準備が整いました。");
            Console.ReadLine();
        }
    }
}

このように、プロセス間でリソースを共有する際にもMutexは有効だ。

utexを使ってリソースの同時使用を防ぐ

最後に、Mutexを使ってリソースの同時使用を防ぎつつ、リトライ機能を実装する例を紹介しよう。

C#

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        Mutex mutex = new Mutex();

        for (int i = 0; i < 5; i++)
        {
            ThreadPool.QueueUserWorkItem(state =>
            {
                int retryCount = 3;
                while (retryCount > 0)
                {
                    if (mutex.WaitOne(1000)) // 1秒待機
                    {
                        try
                        {
                            Console.WriteLine($"スレッド {Thread.CurrentThread.ManagedThreadId} がリソースを取得しました。");
                            Thread.Sleep(500); // 処理を模擬
                        }
                        finally
                        {
                            mutex.ReleaseMutex();
                        }
                        break;
                    }
                    else
                    {
                        Console.WriteLine($"スレッド {Thread.CurrentThread.ManagedThreadId} がリソース取得に失敗。再試行...");
                        retryCount--;
                    }
                }
            });
        }

        Console.ReadLine();
    }
}

このように、Mutexを応用すれば、より柔軟な同期処理が可能となる。

まとめ

「Mutex」はスレッド間やプロセス間での排他制御を行うための強力なツールである。その用途は幅広く、さまざまな場面で活用可能だ。詩のように美しいコードを実現するため、ぜひその力を使いこなしてほしい。

このブログを検索

QooQ