.NET TIPS

スレッドの開始時にパラメータを渡すには?[2.0のみ、C#、VB]

デジタルアドバンテージ 遠藤 孝信
2006/04/07

 .NET Frameworkのクラス・ライブラリでは、Threadクラス(System.Threading名前空間)を利用して特定のメソッドを別スレッドで実行させることができる。しかし.NET Framework 1.xでは、そのメソッド(以降、「スレッド・メソッド」と呼ぶ)はパラメータを取ることができなかった*。2.0ではスレッドの開始時にパラメータの指定が可能になっている。

* ThreadPool.QueueUserWorkItemメソッドやデリゲートのBeginInvokeメソッドを使えば、スレッドにパラメータを渡すことができる。ただしそのスレッドは.NET Frameworkが管理するスレッドプールのスレッドとなる。

フィールド経由でスレッド・メソッドにパラメータを渡す

 .NET Framework 1.xでパラメータをスレッド・メソッドに渡すには、あらかじめクラスのフィールドにその値をセットしておくといった処理が必要である。以下のそのサンプル・プログラムを示す。

// thread.cs

using System;
using System.Threading;

public class WorkerClass {

  // スレッドの実行に必要なデータ
  string message;

  public WorkerClass(string s) {
    message = s;
  }

  // 別スレッドで実行されるメソッド
  public void Worker() {
    for (int i = 0; i < 5; i++) {
      Console.WriteLine(message);
    }
  }
}

public class ThreadSample1 {
  static void Main() {

    WorkerClass wc = new WorkerClass("別のスレッド");

    Thread t = new Thread(new ThreadStart(wc.Worker));

    // デリゲートのインスタンス化は省略可
    // Thread t = new Thread(wc.Worker);

    t.Start();

    Console.WriteLine("スレッドを開始しました");
    // 出力例:
    // スレッドを開始しました
    // 別のスレッド
    // 別のスレッド
    // 別のスレッド
    // 別のスレッド
    // 別のスレッド
  }
}

// コンパイル方法:csc thread.cs
フィールド経由でメソッドにパラメータを渡すC#のサンプル・プログラム(thread.cs)

' thread.vb

Imports System
Imports System.Threading

Public Class WorkerClass

  ' スレッドの実行に必要なデータ
  Dim message As String

  Public Sub New(ByVal s As String)
    message = s
  End Sub

  ' 別スレッドで実行されるメソッド
  Public Sub Worker()
    For i As Integer = 1 To 5
      Console.WriteLine(message)
    Next
  End Sub
End Class

Public Class ThreadSample1
  Shared Sub Main()

    Dim wc As New WorkerClass("別のスレッド")

    Dim t As New Thread(New ThreadStart(AddressOf wc.Worker))

    ' デリゲートのインスタンス化は省略可
    ' Dim t As New Thread(AddressOf wc.Worker)

    t.Start()

    Console.WriteLine("スレッドを開始しました")
    ' 出力例:
    ' スレッドを開始しました
    ' 別のスレッド
    ' 別のスレッド
    ' 別のスレッド
    ' 別のスレッド
    ' 別のスレッド
  End Sub
End Class

' コンパイル方法:vbc thread.vb
フィールド経由でメソッドにパラメータを渡すVBのサンプル・プログラム(thread.vb)

ParameterizedThreadStartデリゲートを使ったスレッドの実行

 .NET Framework 2.0では、スレッド・メソッドにobject型のパラメータを1つ持たせることができるようになっている。

 この場合には、これまでのThreadStartデリゲートではなく、.NET Framework 2.0で新しく追加されたParameterizedThreadStartデリゲート(System.Threading名前空間)を経由してスレッド・メソッドを呼び出す。以下にParameterizedThreadStartデリゲートの定義を示す。

delegate void ParameterizedThreadStart(object obj)
Delegate Sub ParameterizedThreadStart(obj As Object)
ParameterizedThreadStartデリゲートの定義(上:C#、下:VB)

 スレッド・メソッドにパラメータとして渡す値は、ThreadクラスのStartメソッドのパラメータで指定する。

 次のサンプル・プログラムは以上の方法を使って上記のサンプル・プログラムを書き換えたものだ。

// pthread.cs

using System;
using System.Threading;

public class ThreadSample2 {

  // 別スレッドで実行されるメソッド
  static void Worker(object o) {

    // キャストが必要
    string message = (string)o;

    for (int i = 0; i < 5; i++) {
      Console.WriteLine(message);
    }
  }

  static void Main() {

    Thread t = new Thread(new ParameterizedThreadStart(Worker));

    // デリゲートのインスタンス化は省略可
    // Thread t = new Thread(Worker);

    t.Start("別のスレッド");

    Console.WriteLine("スレッドを開始しました");
    // 出力例:
    // スレッドを開始しました
    // 別のスレッド
    // 別のスレッド
    // 別のスレッド
    // 別のスレッド
    // 別のスレッド
  }
}

// コンパイル方法:csc pthread.cs
メソッドにパラメータを渡すC#のサンプル・プログラム(pthread.cs)

' pthread.vb

Imports System
Imports System.Threading

Class ThreadSample2
  Shared Sub worker(ByVal o As Object)

    ' キャストが必要
    Dim message As String = CType(o, String)

    For i As Integer = 1 To 5
      Console.WriteLine(message)
    Next
  End Sub

  Shared Sub Main()

    Dim t As Thread = new Thread(new ParameterizedThreadStart(AddressOf worker))

    ' デリゲートのインスタンス化は省略可
    ' Dim t As New Thread(AddressOf worker)

    t.Start("別のスレッド")

    Console.WriteLine("スレッドを開始しました")
    ' 出力例:
    ' スレッドを開始しました
    ' 別のスレッド
    ' 別のスレッド
    ' 別のスレッド
    ' 別のスレッド
    ' 別のスレッド
  End Sub

End Class

' コンパイル方法:vbc pthread.vb
メソッドにパラメータを渡すVBのサンプル・プログラム(pthread.vb)

 コード内のコメントでも示しているが、C# 2.0やVisual Basic 2005ではデリゲートのインスタンス化(コンストラクタの呼び出し)を省略できる*

* 実際には、スレッド・メソッドがパラメータを取らなければThreadStartデリゲートのコンストラクタの呼び出しがコンパイラにより自動生成され、object型のパラメータを1つ取る場合にはParameterizedThreadStartデリゲートのコンストラクタの呼び出しが自動生成される。

 なお、スレッド・メソッドのパラメータはobject型であるため、上記のサンプル・プログラムのように、たいていの場合でパラメータの明示的なキャストが必要となる。つまりスレッド・メソッドのパラメータはタイプ・セーフではないため、実装に関しては注意が必要だ。

利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:クラス・ライブラリ 処理対象:スレッド
使用ライブラリ:Threadクラス(System.Threading名前空間)
使用ライブラリ:ParameterizedThreadStartデリゲート(System.Threading名前空間)

この記事と関連性の高い別の.NET TIPS
ControlクラスのInvokeメソッドで匿名メソッドを使うには?
汎用的に使用できる定義済みのデリゲート型は?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間