VBでマルチスレッド(BackgroundWorker)
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イベントが発生します。ここで別スレッドの結果を得ることができます。