Silverlight をインストールするには、ここをクリックします*
Japan変更|すべてのMicrosoft のサイト|サインイン
MSDN*
マイクロソフト サイトの検索:
|MSDN ライブラリ|デベロッパー センター|ダウンロード情報|開発ツール製品|コミュニティ|ご意見・ご要望|サイトマップ
MSDN Home  
MSDN Home > .NET Framework > .NET 開発者への道 〜 スキルアップキャンペーン 〜 > .NET Framework 2.0 コア機能解説 > 第 6 回 スレッド処理の強化

.NET Framework 2.0 コア機能解説
〜 第 6 回 スレッド処理の強化 〜

青柳 臣一
Microsoft MVP for Visual Developer - Visual C#

◆スレッド処理の強化

.NET Framework 2.0ではスレッド関連の機能も強化されています。主要なものをご紹介します。

◆パラメータを渡してスレッドを実行

スレッドを実行する際になんらかのパラメータを渡したいことがあります。.NET Framework 1.0/1.1では直接スレッドに渡す方法はありませんでした。そのためスレッドメソッドをラップしたクラスを用意するなどして間接的にパラメータを渡す必要がありました。さまざまな実装方法がありますが、たとえば以下のような形になるでしょう。

C#の例 (1.0、1.1)
private class ThreadClass1x
{
    private string param;

    public ThreadClass1x(string param)
    {
        this.param = param;
    }

    public void Start()
    {
        Thread thread = new Thread(ThreadFunc);
        thread.Start();
    }

    private void ThreadFunc()
    {
        Console.WriteLine("1x: {0}", this.param);
    }
}

private void RunThread1x()
{
    ThreadClass1x threadClass = new ThreadClass1x("parameter");
    threadClass.Start();
}
Visual Basicの例 (1.0、1.1)
Private Class ThreadClass1x
    Private param As String

    Public Sub New(ByVal param As String)
        Me.param = param
    End Sub

    Public Sub Start()
        Dim thread As Thread = New Thread(AddressOf ThreadFunc)
        thread.Start()
    End Sub

    Private Sub ThreadFunc()
        Console.WriteLine("1x: {0}", Me.param)
    End Sub
End Class

Private Sub RunThread1x()
    Dim threadClass As ThreadClass1x = New ThreadClass1x("parameter")
    threadClass.Start()
End Sub

.NET Framework 2.0ではスレッドに直接パラメータを渡す機能が追加されました。 System.Threading.ParameterizedThreadStartデリゲートが追加され、このデリゲートを引数に取るSystem.Threading.Threadクラスのコンストラクタも追加されています。また、Thread.Start(Object parameter)メソッドも追加されてます(以前は引数を取らないStart()メソッドのみでした)。これらを使用すると以下のサンプルコードのように直接スレッドにパラメータを渡すことができます。

C#の例 (2.0)
private void ThreadFunc20(object param)
{
    Console.WriteLine("20: {0}", (string)param);
}

private void RunThread20()
{
    Thread thread = new Thread(ThreadFunc20);
    thread.Start("parameter");
}
Visual Basicの例 (2.0)
Private Sub ThreadFunc20(ByVal param As Object)
    Console.WriteLine("20: {0}", CType(param, String))
End Sub

Private Sub RunThread20()
    Dim thread As Thread = New Thread(AddressOf ThreadFunc20)
    thread.Start("parameter")
End Sub

なお、ParameterizedThreadStartデリゲートのパラメータの型はObjectとなっています。ですので、配列・コレクションを使用して複数の値を渡すこともできますし、別途パラメータ渡し用のクラスを定義してそのインスタンスを渡すこともできます。

◆名前付きイベント

Mutexクラスはコンストラクタで名前を指定することにより名前付きミューテックスとすることができます。名前付きミューテックスであればスレッド間だけでなくプロセス間の同期を取ることも可能になります。

それに対して、AutoResetEventクラス、ManualResetEventクラスには名前を指定することができませんでした。そのため、これらのクラスはスレッド間の同期にのみ使用できます。

.NET Framework 2.0ではEventWaitHandleクラスが追加され、名前付きイベントを作成することが可能になりました。このクラスは事実上AutoResetEventクラス、ManualResetEventクラスを1つにまとめ、かつ、名前を付けられるようにしたものと言っていいかと思います。なお、Auto、Manualの指定もコンストラクタで行います。また、EventWaitHandleクラスもWaitHandleクラスを継承しています。ですので、MutexやAutoResetEventなど他の同期オブジェクトと混在してWaitHandle.WaitAll()メソッドなどで待ち合わせすることも可能です。

C#の例
EventWaitHandle evnt = new EventWaitHandle(false, EventResetMode.ManualReset, "global event");
evnt.WaitOne();
Visual Basicの例
Dim evnt As EventWaitHandle = New EventWaitHandle(False, EventResetMode.ManualReset, "global event")
evnt.WaitOne()

◆セマフォ

.NET Framework 2.0ではSystem.Threading. Semaphoreクラスが追加されました。セマフォを使用すると、リソースへの同時アクセスの最大数を制限することができます。

以下のサンプルコードでは、最大同時アクセス数を2に指定したセマフォを作成し、4つのスレッドに渡しています。それぞれのスレッドではSemaphore.WaitOne()メソッドでロックを獲得し、1秒間スリープした後、Semaphore.Release()メソッドでロックを解放しています。同時にロックを獲得できるのは最大2つですから、3つ目にロックを獲得しようとしたスレッドは最初のスレッドがロックを解放するまで待たされることになります。

C#の例
private class SemaphoreSampleParameter
{
    public Semaphore semaphore;
    public int num;

    public SemaphoreSampleParameter(Semaphore semaphore, int num)
    {
        this.semaphore = semaphore;
        this.num = num;
    }
}

private static void SemaphoreSampleThreadMethod(object param)
{
    SemaphoreSampleParameter p = (SemaphoreSampleParameter)param;
    p.semaphore.WaitOne();
    Console.WriteLine("開始:{0:d}", p.num);
    Thread.Sleep(1000);
    Console.WriteLine("終了:{0:d}", p.num);
    p.semaphore.Release();
}

static void Main(string[] args)
{
    Semaphore semaphore = new Semaphore(0, 2);
    for (int i = 0; i < 4; ++i)
    {
        Thread thread = new Thread(SemaphoreSampleThreadMethod);
        thread.Start(new SemaphoreSampleParameter(semaphore, i));
        Thread.Sleep(200);
    }
    semaphore.Release(2);
    Console.WriteLine("完了");
}

Visual Basicの例
Private Class SemaphoreSampleParameter
    Public semaphore As Semaphore
    Public num As Integer

    Public Sub New(ByVal semaphore As Semaphore, ByVal num As Integer)
        Me.semaphore = semaphore
        Me.num = num
    End Sub
End Class

Private Sub SemaphoreSampleThreadMethod(ByVal param As Object)
    Dim p As SemaphoreSampleParameter = CType(param, SemaphoreSampleParameter)
    p.semaphore.WaitOne()
    Console.WriteLine("開始:{0:d}", p.num)
    Thread.Sleep(1000)
    Console.WriteLine("終了:{0:d}", p.num)
    p.semaphore.Release()
End Sub

Sub Main()
    Dim semaphore As Semaphore = New Semaphore(0, 2)
    For i As Integer = 0 To 3
        Dim th As Thread = New Thread(AddressOf SemaphoreSampleThreadMethod)
        th.Start(New SemaphoreSampleParameter(semaphore, i))
        Thread.Sleep(200)
    Next
    semaphore.Release(2)
    Console.WriteLine("完了")
End Sub

◆スレッドのスタックサイズ

.NET Framework 2.0ではSystem.Threading.Thread.Start()メソッドでスレッドのスタックサイズを指定することができるようになりました。

◆参考資料

System.Threading.Threadクラス
http://msdn2.microsoft.com/ja-jp/library/system.threading.thread.aspx

System.Threading.EventWaitHandleクラス
http://msdn2.microsoft.com/ja-jp/library/system.threading.eventwaithandle.aspx

System.Threading.Semaphoreクラス
http://msdn2.microsoft.com/ja-jp/library/system.threading.semaphore.aspx

Top of Page Top of Page


Microsoft