VBでマルチスレッド

VB2005では、BackgroundWorkerコントロールを使うことで簡単にマルチスレッド プログラミングを作成することができます。

ツールボックス

このBackgroundWorkerには、いくつかのイベントが用意されています。

DoWork
スレッドの開始時に呼ばれます。(RunWorkerAsyncが呼び出されたときに発生します。)
ProgressChanged
ReportProgressが呼び出されたときに発生します。進捗具合などをここで表示します。
RunWorkerCompleted
バックグラウンド操作の完了時、キャンセル時、またはバックグラウンド操作によって例外が発生したときに発生します。
Disposed

BackgroundWorkerの例

BackgroundWorkerは、時間のかかる処理を裏(別のスレッド)で処理をさせ、親フォームに 進捗を表示するといった作業を容易に実現できます。

Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
           Handles btnStart.Click

    ' スレッドの開始
    backgroundworker.RunWorkerAsync()
End Sub
Private Sub backgroundworker_DoWork(ByVal sender As Object, _
             ByVal e As System.ComponentModel.DoWorkEventArgs) Handles backgroundworker.DoWork

    ' BackgroundWorkerの取得(スレッドを作成したオブジェクト)
    Dim objWorker As System.ComponentModel.BackgroundWorker = _
                CType(sender, System.ComponentModel.BackgroundWorker)
    
    ' 時間のかかる裏で動かしたい処理
    e.Result = CountThread(objWorker, e)

End Sub
Private Function CountThread(ByVal worker As System.ComponentModel.BackgroundWorker, _
    ByVal e As System.ComponentModel.DoWorkEventArgs) As Long

    Dim result As Long = 0
    Dim intProgress As Integer

    ' 印刷処理だと思って
    For i As Integer = 1 To 60000
        ' スレッドキャンセルの確認
        If worker.CancellationPending Then
            e.Cancel = True
            Exit For
        Else
           ・・・
            intProgress = CType(CSng(i) / CSng(60000) * 100, Integer)

            ' ProgressChangedイベントを発生させる
            worker.ReportProgress(intProgress)
        End If
    Next

    Return result
End Function
' 進捗状況更新イベント
Private Sub backgroundworker_ProgressChanged(ByVal sender As Object, _
              ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
              Handles backgroundworker.ProgressChanged

    ' パーセンテージの場合 e.ProgressPercentage で取得可能
    prgStatus.Value = e.ProgressPercentage
    prgStatus.Update()
End Sub
' スレッド処理終了
Private Sub backgroundworker_RunWorkerCompleted(ByVal sender As Object, _
             ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
             Handles backgroundworker.RunWorkerCompleted

    ' 最初に、例外がスローされた場合の処理
    If Not (e.Error Is Nothing) Then
        MessageBox.Show(e.Error.Message)
    ElseIf e.Cancelled Then
        ' 次に、ユーザーが計算をキャンセルした場合の処理
        ・・・
    Else
        ' 正常に完了した場合の処理
        ・・・
    End If
End Sub

別スレッドを開始するトリガーとなるのが、BackgroundWorkerのRunWorkerAsync()関数になります。

RunWorkerAsyncによりDoWorkイベントが発生します。

スレッド側に引数を渡したい場合、RunWorkerAsync関数で渡すことができます。RunWorkerAsyncで渡した 引数は、DoWorkのDoWorkEventArgs.Argumentで受取ることができます。

進捗具合を送信するには、スレッド内でReportProgress関数を呼びます。この関数により ProgressChangedイベントが発生します。

ReportProgressを使用する場合、BackgroundWorkerコントロールのWorkerReportsProgressプロパティを Trueにしておく必要があります。

スレッドが終了するとRunWorkerCompletedイベントが発生します。ここで別スレッドの結果を得ることができます。