マルチスレッド?なんだそりゃという方のためにスレッドについて簡単に説明します。
スレッドとは直訳すると、撚り糸、筋、脈絡という意味ですが、プログラム世界では最小の処理単位のことを言います。
マルチスレッドとは同時に複数の処理を行うことを指します。
具体的に説明をすると、「歩く」というスレッドと「スマホをいじる」というスレッドがあるとします。
その場合、「歩きスマホ」がマルチスレッドということになります。
10分間歩き、10分間スマホをいじる場合に、別々に行うと計20分かかります。
それをメインスレッドが「歩く」バックグラウンドのスレッドが「スマホをいじる」を同時に行うことで10分で完了できます。
例に挙げましたが、歩きスマホは危険なのでやめましょう!!
VB.NETで仕様できるスレッドにはいくつか種類がありますが、ここではBackgroundWorkerの使い方を説明します。
事前準備
BackgroundWokerを使用するためには、ツールボックスからBackgroundWokerをFormにドラッグ&ドロップします。
下記のようになればBackgroundWokerを使う準備はOKです。
※名称が長いため、BackgroundWoker1をbgwとします。
スレッド処理したい処理を書く
Private Sub bgw_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork For I As Integer = 1 To 100 'ここに時間のかかる処理を書く Next End Sub
処理の実行
RunWorkerAsyncメソッドを実行します。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click bgw.RunWorkerAsync() End Sub
処理状況を通知
メインスレッドとバックグラウンドのスレッドは別スレッドの処理のため互いがどんな状況にあるかがわかりません。
そこで、バックグラウンドスレッドがメインスレッドに状況を通知するために使用するのがProgressChangedイベントです。
代表的なもので、プログレスバーがあります。
100回の処理があり、1つ終わるごとに1%の処理が完了したものとするとしましょう。
その場合に、メインスレッドに完了の通知を投げることができます。
ここで注意すべきなのが、あくまでも通知ができるものなのでProgressChanged内でメインスレッドとなる親のコントロール(テキストボックスやラベルなど)に対してアクセスすることはできません。
また、事前にWorkerReportsProgress=Trueにする必要があります。
通知する側
Private Sub bgw_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork For i As Integer = 1 To 100 '〜時間のかかる処理〜 'ProgressChangedイベントで処理状況を通知 bgw.ReportProgress(i Next End Sub
受ける側
Private Sub bgw_ProgressChanged(sender As System.Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged 'プログレスバーを更新 ProgressBar1.Value = e.ProgressPercentage End Sub
処理完了を通知
RunWorkerCompletedイベントを使用します。
' バックグラウンド処理完了時の処理 Private Sub bgw_RunWorkerCompleted(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgw.RunWorkerCompleted MessageBox.Show("処理が完了しました。") End Sub
キャンセルをするには
CancelAsyncを使用します。
また、事前にWorkerSupportsCancellation=Trueにする必要があります。
Private Sub btnCancel_Click(sender As System.Object, e As System.EventArgs) Handles btnCancel.Click '処理が実行中か? If bgw.IsBusy Then 'キャンセル bgw.CancelAsync() End If End Sub