マルチスレッド プロシージャのパラメータと戻り値
更新 : 2007 年 11 月
スレッド クラスのコンストラクタは、引数を取らず値を返さないプロシージャに参照を渡す必要があるため、マルチスレッド アプリケーションでの値の受け渡しは複雑です。以下のセクションでは、異なるスレッドのプロシージャからパラメータを指定して値を返す単純な方法を示します。
マルチスレッド プロシージャのパラメータの指定
マルチスレッド メソッドの呼び出しにパラメータを指定する最良の方法は、クラスにターゲット メソッドをラップし、新規スレッドのパラメータとして機能するフィールドをそのクラスに対して定義することです。この方法の利点は、新規スレッドを開始するたびに独自のパラメータでクラスの新規インスタンスを作成できることです。たとえば、次のコードに示すように三角形の面積を計算する関数があるとします。
Function CalcArea(ByVal Base As Double, ByVal Height As Double) As Double
CalcArea = 0.5 * Base * Height
End Function
CalcArea 関数をラップして入力パラメータを格納するフィールドを作成するクラスを記述するコードは次のとおりです。
Class AreaClass
Public Base As Double
Public Height As Double
Public Area As Double
Sub CalcArea()
Area = 0.5 * Base * Height
MsgBox("The area is: " & Area)
End Sub
End Class
AreaClass を使用するには、次のコードに示すように AreaClass オブジェクトを作成し、Base プロパティと Height プロパティを設定します。
Protected Sub TestArea()
Dim AreaObject As New AreaClass
Dim Thread As New System.Threading.Thread _
(AddressOf AreaObject.CalcArea)
AreaObject.Base = 30
AreaObject.Height = 40
Thread.Start()
End Sub
TestArea プロシージャは CalcArea メソッドの呼び出し後に Area フィールドの値を確認しないことに注意してください。CalcArea は別のスレッドで実行されるため、Thread.Start を呼び出した直後に確認する場合は、Area フィールドが設定されているとは限りません。次のセクションでは、マルチスレッド プロシージャから値を返す適切な方法について説明します。
マルチスレッド プロシージャからの戻り値
異なるスレッドで実行されるプロシージャの場合、値を返す動作は複雑になります。プロシージャは関数にすることができず、ByRef 引数を使用できないからです。値を返す最も簡単な方法は、BackgroundWorker コンポーネントを使ってスレッドを管理し、タスクが完了したときにイベントを生成し、結果をイベント ハンドラで処理することです。
次の例では、別のスレッドで実行中のプロシージャからイベントを発生させて値を返します。
Private Class AreaClass2
Public Base As Double
Public Height As Double
Function CalcArea() As Double
' Calculate the area of a triangle.
Return 0.5 * Base * Height
End Function
End Class
Private WithEvents BackgroundWorker1 As New System.ComponentModel.BackgroundWorker
Private Sub TestArea2()
Dim AreaObject2 As New AreaClass2
AreaObject2.Base = 30
AreaObject2.Height = 40
' Start the asynchronous operation.
BackgroundWorker1.RunWorkerAsync(AreaObject2)
End Sub
' This method runs on the background thread when it starts.
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles BackgroundWorker1.DoWork
Dim AreaObject2 As AreaClass2 = CType(e.Argument, AreaClass2)
' Return the value through the Result property.
e.Result = AreaObject2.CalcArea()
End Sub
' This method runs on the main thread when the background thread finishes.
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles BackgroundWorker1.RunWorkerCompleted
' Access the result through the Result property.
Dim Area As Double = CDbl(e.Result)
MsgBox("The area is: " & Area)
End Sub
スレッド プールのスレッドにパラメータと戻り値を用意するには、QueueUserWorkItem メソッドの省略可能な状態オブジェクト変数 (ByVal) を使用します。スレッド タイマのスレッドもこの目的で状態オブジェクトをサポートしています。スレッド プールおよびスレッド タイマの詳細については、「スレッド プール」および「スレッド タイマ」を参照してください。