サンプル コードのダウンロード (vbmigtips_BackgroundWorker.msi, 489 KB)
※ このサンプルをインストールするには Visual Studio 2005 が必要です。
スレッド機能を使用することで、アプリケーションの動作を止めることなく効率よく処理を実行することができます。そこで今回は、ProgressBar コントロールを使用して、スレッドの実行方法について紹介します。今回は、別スレッドを作成し、スレッドから ProgressBar コントロールを操作して実行状況を表示します。
Visual Basic 6.0 では、スレッド機能はサポートされていません。スレッドは、Visual Basic .NET よりサポートされ、Visual Basic 2005 では、BackgroundWorker クラスが新たにサポートされたことにより、Visual Basic .NET では複雑だったスレッドの処理を簡単に行うことができるようになりました。今回は、Visual Basic .NET での実装方法と、Visual Basic 2005 でのスレッドの処理方法について紹介します。
まず、Visual Basic .NET での実装方法について紹介します。この方法は、Visual Basic 2005 でも動作します。
別スレッドからコントロールの操作を行う場合、Visual Basic .NET では、Invoke メソッドを使用します。この Invoke メソッドを使用してメソッドを呼び出すことで、コントロールを作成したメイン スレッドによって実行されます。実装コードは以下のとおりです。
Private Delegate Sub CallDelegate()
Private objThread As System.Threading.Thread
Private Sub VS2003StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
VS2003StartButton.Click
VS2003StartButton.Enabled = False
objThread = New System.Threading.Thread(AddressOf doWork)
objThread.Start()
End Sub
Private Sub VS2003NextButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
VS2003NextButton.Click
MessageBox.Show("完了しました。")
End Sub
Private Sub doWork()
Dim i As Integer
For i = 1 To 20
System.Threading.Thread.Sleep(500)
Me.Invoke(New CallDelegate(AddressOf SetValue))
Next
Invoke(New CallDelegate(AddressOf SetFocus))
End Sub
Private Sub SetValue()
VS2003ProgressBar.Value += 1
End Sub
Private Sub SetFocus()
VS2003NextButton.Enabled = True
VS2003NextButton.Focus()
End Sub
リスト1
上記 (リスト1) の「Private Sub VS2003StartButton_Click(ByVal ... End Sub」では、スレッドを作成し、実行します。「objThread = New System.Threading.Thread(AddressOf doWork)」で doWork メソッドとして作成し、「objThread.Start()」でスレッドを実行します。
「Private Sub doWork() ... End Sub」では、スレッドで実行される処理のプロシージャを宣言します。doWork メソッドは別スレッドで実行されるため、「Me.Invoke(New CallDelegate(AddressOf SetValue))」や「Invoke(New CallDelegate(AddressOf SetFocus))」のように、Inovke メソッドを使用して、doWork メソッドからコントロールを操作します。コントロールの操作は、SetValue メソッドや SetFocus メソッドを利用します。「System.Threading.Thread.Sleep(500)」で 500 ミリ秒間スレッドを一時中断し、SetValue メソッドを使用して、ProgressBar の表示を一定量ずつ増やしていきます。最後に SetFocus メソッドを使用して「次へ」のボタンにフォーカスを移動させます。
これらを実装し、[開始]ボタンを選択すると、スレッドが作成され、実行します。スレッドが実行中、ProgressBar に進歩状況が表示されます (図1)。
.jpg)
図1
このように、Visual Basic .NET で別スレッドからコントロールを操作する場合、Delegate、Invoke、AddressOf など使用します。一方、Viusal Basic 2005 では、BackgroundWorker クラスがサポートされたことにより Delegate、Invoke、AddressOf などを利用せずに実装することができるようになりました。そこで続いては、BackgroundWorker クラスを使用しての別スレッドからのコントロールの操作方法を紹介します。
BackgroundWorker クラスの RunWorkerAsync メソッド でバックグラウンド操作の実行を開始し、DoWork イベントを発生させます。 これは、リスト1 の「objThread = New System.Threading.Thread(AddressOf doWork)」「objThread.Start()」と同等の処理です。また、ReportProgress メソッドは、ProgressChanged イベントを発生させます。これにより、リスト1 の「Me.Invoke(New CallDelegate(AddressOf SetValue))」と同等の処理を実装することができます。BackgroundWorker クラスを使用した場合、リスト1 の doWork メソッドは、DoWork イベント ハンドラに対応し、リスト1 の SetValue メソッドは ProgressChanged イベント ハンドラに対応します。
今回は、Visual Basic .NET で作成したリスト1 と同等の処理を BackgroundWorker コントロールを使用して実装する方法を紹介します。実装コードは以下のとおりです (事前に[ツールボックス]から BackgroundWorker コントロールを Form に貼り付けておきます) 。
Private Sub VS2005StartButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles VS2005StartButton.Click
VS2005StartButton.Enabled = False
Me.BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub VS2005NextButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
VS2005NextButton.Click
MessageBox.Show("完了しました。")
End Sub
Private Sub VS2005ProgressBar_DoWork(ByVal sender As
Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim i As Integer
For i = 1 To 20
System.Threading.Thread.Sleep(500)
BackgroundWorker1.ReportProgress(i)
Next
End Sub
Private Sub VS2005ProgressBar_ProgressChanged(ByVal sender As System.Object, ByVal e As
System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
VS2005ProgressBar.Value = e.ProgressPercentage
End Sub
Private Sub VS2005ProgressBar_RunWorkerCompleted(ByVal sender As Object, ByVal e As
System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
VS2005NextButton.Enabled = True
VS2005NextButton.Focus()
End Sub
リスト2
上記 (リスト2) の「Me.BackgroundWorker1.RunWorkerAsync()」でバックグラウンド操作の実行を開始します。「System.Threading.Thread.Sleep(500)」で 500 ミリ秒間スレッドを一時中断し、「BackgroundWorker1.ReportProgress(i) 」で ProgressChanged イベントを発生させます。これにより、ProgressChanged イベント ハンドラの「VS2005ProgressBar.Value = e.ProgressPercentage」で ProgressBar の表示を一定量ずつ増やしていきます。RunWorkerCompleted イベント ハンドラ (「Private Sub VS2005ProgressBar_RunWorkerCompleted(ByVal ... End Sub」) は、バックグラウンド操作が完了した時やキャンセル時、バックグラウンド操作によって例外が発生したときなど発生します。今回は、リスト1 の SetFocus メソッドの処理をここで実装しています。
リスト2を実装し、[開始]ボタンを選択すると、バックグラウンド操作を実行し、ProgressBar に進歩状況が表示されます (図2)。
.jpg)
図2