VB.NET バックグラウンド処理 BackgroundWorker

VB.NETにおけるバックグラウンド処理について紹介していきます。

バックグランド処理は、マルチタスクなど複数の処理を同時に実行している時に、
ユーザには見えない裏側で処理が行われる処理のことです。

時間がかかる重たい処理を実行する時に、普通に実行すると、
処理が終了するまで画面を触ることができなくなってしまいます。
重たい処理を実行している時も別の操作はできるようにしておきたい時などにバックグラウンド処理を使用します。

通常、バックグラウンド処理の実装は、少し難しいのですが、
VB.NETには、BackGroundWorkerというものがあり、比較的簡単に実装することができます。

今回はBackGroundWorkerの使用方法を見ていきましょう。

BackGroundWorkerの配置

ツールボックスからBackGroundWorkerを選択して画面に配置しましょう。
BackGroundWorkerは、コンポーネントのところにあります。

これで配置は完成です。
また、ボタンを3つとラベルも配置しております。

BackGroundWorkerの使い方は、例を見ながら使っていきましょう。

画面の概要

実行ボタン押下
1~10まで1秒おきに、カウントする。その際に実行ボタン下のカウント結果をLabelに記載する。
10秒処理に時間がかかるので、この処理をバックグラウンドで処理しましょう。

msgボタン押下
メッセージボックスを表示する。

キャンセルボタン
実行中の処理をキャンセルする。

このような3機能を持つ画面を作成していきます。

BackGroundWorkerのイベント

BackGroundWorkerには、3つのイベントがあるので、順番に紹介していきます。

1DoWork バックグラウンド処理

BackGroundWorker.Doworkイベントは、バックグランドで処理をする内容を記載することができます。(データの更新やファイル書き込み などなど)
ただし、ここではラベルのTextの設定など、画面コントロールへの書き込みをすることができません。

2ProgressChanged 進捗状況表示

BackGroundWorker.ProgressChangedイベントは、画面コントロールへの書き込みをすることができます。
主にバックグラウンド処理の進捗を表示する時に使用するイベントになっています。

3RunWorkerCompleted 後処理

BackgroundWorker1.RunWorkerCompletedイベントは、DoWorkイベントが完了した後、後処理を行いたい場合に記載するイベントです。
DoWorkが正常で終わった時、異常で終わった時、キャンセルされた時と状況に合わせた処理を記載します。

 

BackGroundWorkerの使い方

BackGroundWorkerのプロパティの設定

まずBackGroundWorkerのプロパティを2つ設定します。

今回はロードイベントで記載しています。デザインのプロパティでも設定できます。

Private Sub frmBackGroundWork_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    'ProgressChangedイベントを使用する時
    BackgroundWorker1.WorkerReportsProgress = True
    'キャンセル処理を行う時
    BackgroundWorker1.WorkerSupportsCancellation = True
End Sub

 

BackgroundWorker.DoWorkイベント

次にBackGroudWorker.DoWorkイベントを呼び出す方法を記載します。

BackgroundWorker.RunWorkerAsync(パラメータ)

実際の例を見てみましょう。
今回の例では、実行ボタン押下時に呼び出します。

Private Sub btnJiko_Click(sender As Object, e As EventArgs) Handles btnJiko.Click
    BackgroundWorker1.RunWorkerAsync(10)
End Sub

BackgroundWorker1.RunWorkerAsync(10)により以下のイベントが呼び出されます。
ここからがDoWorkイベントの内容になります。

Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork

    Dim bgWorker As BackgroundWorker = DirectCast(sender, BackgroundWorker)

    'パラメータを取得する
    Dim maxLoops As Integer = CInt(e.Argument)

    For i As Integer = 1 To maxLoops

        If bgWorker.CancellationPending = True Then
            e.Cancel = True
            Exit Sub
        End If

        bgWorker.ReportProgress(i)
        Threading.Thread.Sleep(1000)

    Next

    e.Result = "処理完了"

End Sub

解説
3行目:BackGroundWorker1を取得する
6行目:呼び出し元のパラメータを取得。今回は10が取得できます。
8行目:1~10までループ
10~13行目:もし、キャンセルボタンが押されている場合、CancellationPendingがTrueとなり、ここの処理を通る。
15行目:bgWorker.ReportProgress(i)でProgressChangedイベントを呼び出します。
16行目:1秒待機
20行目:結果に値を設定。RunWorkerCompletedイベントで使用できます。

 

ProgressChangedイベント

ProgressChangedイベントの内容、DoWorkイベントの進捗を画面に表示するイベントです。

Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    Dim result As Integer = CInt(e.ProgressPercentage)
    Label1.Text = result.ToString & "件"
End Sub

解説
2行目:e.ProgressPercentageでパラメータの取得をしています。呼び出し元で(i)を設定しているのでループのカウントが取得できています。
3行目:ラベルの値を更新

 

RunWorkerCompletedイベント

RunWorkerCompletedイベントの内容

Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted

    If e.Cancelled = True Then
        MsgBox("キャンセルしました")
    ElseIf Not e.Error Is Nothing Then
        MsgBox(e.Error.ToString)
    ElseIf e.Result.ToString <> String.Empty Then
        MsgBox(e.Result.ToString)
    End If

End Sub

解説
3行目:キャンセルボタンを押下されたときの対応
5行目:異常処理
7行目:正常処理

キャンセル処理

キャンセルボタンの処理
BackgroundWorker1.CancelAsync()でDoWorkイベントの10行目のbgWorker.CancellationPending = Trueに処理が入ります。

Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
    BackgroundWorker1.CancelAsync()
End Sub

 

msgボタンの処理
メッセージを表示します。

Private Sub btnMsg_Click(sender As Object, e As EventArgs) Handles btnMsg.Click
    MsgBox("こんにちは")
End Sub

 

結果

実行ボタンを押下し処理の途中でも、msgボタンを押下することができることが確認できました。

 

 

サンプルコード

Imports System.ComponentModel

Public Class frmBackGroundWork

    Private Sub frmBackGroundWork_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'backgroundworkerのプロパティ設定
        BackgroundWorker1.WorkerReportsProgress = True
        BackgroundWorker1.WorkerSupportsCancellation = True
    End Sub

    Private Sub btnJiko_Click(sender As Object, e As EventArgs) Handles btnJiko.Click
        BackgroundWorker1.RunWorkerAsync(10)
    End Sub

    Private Sub btnMsg_Click(sender As Object, e As EventArgs) Handles btnMsg.Click
        MsgBox("こんにちは")
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork

        Dim bgWorker As BackgroundWorker = DirectCast(sender, BackgroundWorker)

        'パラメータを取得する
        Dim maxLoops As Integer = CInt(e.Argument)

        For i As Integer = 1 To maxLoops

            If bgWorker.CancellationPending = True Then
                e.Cancel = True
                Exit Sub
            End If

            bgWorker.ReportProgress(i)
            Threading.Thread.Sleep(1000)

        Next

        e.Result = "処理完了"

    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged

        Dim result As Integer = CInt(e.ProgressPercentage)
        Label1.Text = result.ToString & "件"

    End Sub

    Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted

        If e.Cancelled = True Then
            MsgBox("キャンセルしました")
        ElseIf e.Result.ToString <> String.Empty Then
            MsgBox(e.Result.ToString)
        Else
            MsgBox("異常終了しました")
        End If

    End Sub

    Private Sub btnCancel_Click(sender As Object, e As EventArgs) Handles btnCancel.Click
        BackgroundWorker1.CancelAsync()
    End Sub
End Class

 

まとめ

バックグラウンド処理を使用する時は、BackgroundWorkerを利用しましょう。
その時に、処理の流れを覚えておくと理解しやすいと思います。

処理の流れ
  • ①BackgroundWorker.RunWorkerAsync(パラメータ)でDoWorkイベントを呼び出す。
  • ②DoWorkイベント バックグラウンド処理を実行
  • ③キャンセルしたい場合は、BackgroundWorker1.CancelAsync()を実行する
  • ④bgWorker.CancellationPending = Trueの場合はキャンセル処理
  • ⑤DoWorkが完了すると、BackgroundWorker1.RunWorkerCompletedイベントが呼び出される。

③④はキャンセル処理が必要な場合のみです。

 

VB.NETの記事一覧

おすすめの記事