Share via


マルチスレッド プロシージャのパラメータと戻り値

更新 : 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) を使用します。スレッド タイマのスレッドもこの目的で状態オブジェクトをサポートしています。スレッド プールおよびスレッド タイマの詳細については、「スレッド プール」および「スレッド タイマ」を参照してください。

参照

概念

スレッド状態

スレッド プール

スレッドの同期

イベントとイベント ハンドラ

マルチスレッド アプリケーション

フォームとコントロールでのマルチスレッド

デリゲートと AddressOf 演算子

その他の技術情報

コンポーネントのマルチスレッド