[BackgroundWorker][Tips] バックグランド操作にパラメーターを渡す


バックグラウンド操作を実行するとき(RunWorkerAsyncメソッド実行時)にはパラメーターを渡すことができます。

RunWorkerAsyncメソッドの引数に値を渡すと、バックグラウンド操作(DoWorkイベント)のe.Argumentプロパティで受け取ることができます。

下記は、バックグランド操作にパラメーターを渡す例です。

RunWorkerAsyncメソッドに100を渡して、DoWorkイベントで受け取り、ループの最大値として使用しています。

VBの例

' [START]ボタンクリック時の処理
Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click
    ' [START]ボタンを無効にする
    btnStart.Enabled = False

    '進捗状況の報告をできるようにする
    BackgroundWorker1.WorkerReportsProgress = True

    'バックグラウンド処理を開始する(パラメーターとして100を渡す)
    BackgroundWorker1.RunWorkerAsync(100)
End Sub

' 時間のかかる処理を実行する
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    '★★★受け取ったパラメータをループの最大値にする★★★
    Dim iLoopMax As Integer = CInt(e.Argument)

    For I As Integer = 1 To iLoopMax
        '200mSecスリープさせる
        System.Threading.Thread.Sleep(200)

        'ProgressChangedイベントを発生させる
        BackgroundWorker1.ReportProgress(I)
    Next
End Sub

' 進捗状況を更新する
Private Sub BackgroundWorker1_ProgressChanged(sender As System.Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    'プログレスバーを進捗させる
    ProgressBar1.Value = e.ProgressPercentage
End Sub

' バックグラウンド処理完了時の処理
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    'バックグラウンド処理が完了したので[START]ボタンを有効にする
    btnStart.Enabled = True
End Sub

C#の例

// [START]ボタンクリック時の処理
private void btnStart_Click(object sender, EventArgs e)
{
    // [START]ボタンを無効にする
    btnStart.Enabled = false;

    // 進捗状況の報告をできるようにする
    backgroundWorker1.WorkerReportsProgress = true;

    // ★★★バックグラウンド処理を開始する(パラメーターとして100を渡す)★★★
    backgroundWorker1.RunWorkerAsync(100);
}

// 時間のかかる処理を実行する
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // ★★★受け取ったパラメータをループの最大値にする★★★
    int iLoopMax = (int)e.Argument;

    for (int i = 0; i < iLoopMax; i++)
    {
        // 200mSecスリープさせる
        System.Threading.Thread.Sleep(200);

        // ProgressChangedイベントを発生させる
        backgroundWorker1.ReportProgress(i + 1);
    }
}

// 進捗状況を更新する
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // プログレスバーを進捗させる
    progressBar1.Value = e.ProgressPercentage;
}

// バックグラウンド処理完了時の処理
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // バックグラウンド処理が完了したので[START]ボタンを有効にする
    btnStart.Enabled = true;
}

[BackgroundWorker][Tips] バックグラウンド操作をキャンセルする


BackgroundWorkerコンポーネントを使用してバックグラウンド処理を実行している環境で、操作をキャンセルする方法を紹介します。

バックグラウンド処理を実行する方法については「時間のかかる処理をバックグラウンドで実行する」を参照ください。

バックグラウンド操作を実行できるようにするには、CancelAsyncメソッドを実行します。
CancelAsyncメソッドを実行するには、あらかじめWorkerSupportsCancellationプロパティにTrueを設定しておく必要があります(既定値はFalseです)。
また、BackgroundWorkerインスタンスのIsBusyメソッドを使用して、現在バックグラウンドが処理中かどうかを確認した上(Trueが実行中を示します)で、CancelAsyncメソッドを実行することをおすすめします。

バックグラウンド処理(DoWork)イベント内では、BackgroundWorkerインスタンスのCancellationPendingメソッドを使用して、キャンセル要求が出ているかを確認し(Trueの場合キャンセル処理が出されていることを示します)、e.CancelプロパティにTrueをセットしてイベントをキャンセルします。

キャンセル処理が終了すると、バンクグラウンド処理が正常終了した場合と同様に、RunWorkerCompletedイベントが発生します。キャンセルによってRunWorkerCompletedイベントが発生したかどうかを判断するには、e.CanceledプロパティがTrueかを確認します。

下記は、バックグラウンド操作をキャンセルする例です。

[START]ボタンが押されると、バックグラウンド操作が行われ、[CANCEL]ボタンで操作を中止します。

VBの例

' [START]ボタンクリック時の処理
Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click
    '[START]ボタンを無効にする
    btnStart.Enabled = False
    '[CANCEL]ボタンを有効にする
    btnCancel.Enabled = True

    '進捗状況の報告をできるようにする
    BackgroundWorker1.WorkerReportsProgress = True

    '★★★バックグラウンド処理をキャンセルできるようにする★★★
    BackgroundWorker1.WorkerSupportsCancellation = True

    'バックグラウンド処理を開始する
    BackgroundWorker1.RunWorkerAsync()
End Sub

' [CANCEL]ボタンクリック時の処理
Private Sub btnCancel_Click(sender As System.Object, e As System.EventArgs) Handles btnCancel.Click
    'バックグラウンド処理が実行中か?
    If BackgroundWorker1.IsBusy Then
        '★★★バックグラウンド処理をキャンセルする★★★
        BackgroundWorker1.CancelAsync()
    End If
End Sub

' 時間のかかる処理を実行する
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    For I As Integer = 1 To 100
        '★★★バックグラウンド操作のキャンセル要求が出されているかを確認する★★★
        If BackgroundWorker1.CancellationPending Then
            'イベントをキャンセルする
            e.Cancel = True
            Return
        End If

        '200mSecスリープさせる
        System.Threading.Thread.Sleep(200)

        'ProgressChangedイベントを発生させる
        BackgroundWorker1.ReportProgress(I)
    Next
End Sub

' 進捗状況を更新する
Private Sub BackgroundWorker1_ProgressChanged(sender As System.Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    'プログレスバーを進捗させる
    ProgressBar1.Value = e.ProgressPercentage
End Sub

' バックグラウンド処理完了時の処理
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    '★★★バックグラウンド操作がキャンセルされた場合★★★
    If e.Cancelled Then
        'ボタンとプログレスバーを初期化する
        btnStart.Enabled = True
        btnCancel.Enabled = False
        ProgressBar1.Value = 0

        MessageBox.Show("キャンセルされました!!")
    End If

    'バックグラウンド処理が完了したので[START]ボタンを有効にする
    btnStart.Enabled = True
End Sub

C#の例

// [START]ボタンクリック時の処理
private void btnStart_Click(object sender, EventArgs e)
{
    // [START]ボタンを無効にする
    btnStart.Enabled = false;
    // [CANCEL]ボタンを有効にする
    btnCancel.Enabled = true;

    // 進捗状況の報告をできるようにする
    backgroundWorker1.WorkerReportsProgress = true;

    // ★★★バックグラウンド処理をキャンセルできるようにする★★★
    backgroundWorker1.WorkerSupportsCancellation = true;

    // バックグラウンド処理を開始する
    backgroundWorker1.RunWorkerAsync();
}

// [CANCEL]ボタンクリック時の処理
private void btnCancel_Click(object sender, EventArgs e)
{
    // バックグラウンド処理が実行中か?
    if (backgroundWorker1.IsBusy)
    {
        // ★★★バックグラウンド処理をキャンセルする★★★
        backgroundWorker1.CancelAsync();
    }
}

// 時間のかかる処理を実行する
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i < 100; i++)
    {
        // ★★★バックグラウンド操作のキャンセル要求が出されているかを確認する★★★
        if (backgroundWorker1.CancellationPending)
        {
            // イベントをキャンセルする
            e.Cancel = true;
            return;
        }

        // 200mSecスリープさせる
        System.Threading.Thread.Sleep(200);

        // ProgressChangedイベントを発生させる
        backgroundWorker1.ReportProgress(i + 1);
    }
}

// 進捗状況を更新する
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // プログレスバーを進捗させる
    progressBar1.Value = e.ProgressPercentage;
}

// バックグラウンド処理完了時の処理
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // ★★★バックグラウンド操作がキャンセルされた場合★★★
    if ( e.Cancelled )
    {
        // ボタンとプログレスバーを初期化する
        btnStart.Enabled = true;
        btnCancel.Enabled = false;
        progressBar1.Value = 0;

        MessageBox.Show("キャンセルされました!!");
    }

    // バックグラウンド処理が完了したので[START]ボタンを有効にする
    btnStart.Enabled = true;
}

[BackgroundWorker][Tips] 時間のかかる処理をバックグラウンドで実行する


BackgroundWorkerコンポーネントを使用すると、時間のかかる処理をバックグラウンドで実行することができます。

BackgroundWorkerでバックグラウンド処理を開始するにはRunWorkerAsyncメソッドを実行します。

RunWorkerAsyncメソッドを実行すると、DoWorkイベントが発生します。

時間のかかる処理は、このDoWorkイベント内に記述します。

また、BackgroundWorkerでは進捗を管理することができ、ProgressChangedイベントで進捗状況を更新する処理を記述します。

ProgressChangedイベントは、DowWorkイベント内でReportProgressメソッドを実行することで、発生させることができます(事前にWorkerReportsProgressプロパティにTrueを設定しておく必要があります)。ReportProgressメソッドの引数には、現在の進捗率0~100%を渡す必要があることに注意してください。進捗状況の割合はe.ProgressPercentageプロパティで取得することができます。

最後に、バックグランド処理が完了するとRunWorkerCompletedイベントが発生します。

まとめると下記の手順となります

  • バックグラウンド処理の実行はRunWorkerAsyncメソッドを実行
  • 時間のかかる処理はDoWorkイベントに記述
  • 進捗状況はProgressChangedイベントに記述(あらかじめWorkerReportsProgressプロパティにTrueを設定)
  • 終了処理はRunWorkerCompletedイベントに記述

下記は、時間のかかる処理をバックグラウンドで実行する例です。

[START]ボタンが押されると、時間がかかる処理(200mSecのスリープを100回繰り返しています)を実行し、プログレスバーを進捗させます。

VBの例

' [START]ボタンクリック時の処理
Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click
    ' [START]ボタンを無効にする
    btnStart.Enabled = False

    '進捗状況の報告をできるようにする
    BackgroundWorker1.WorkerReportsProgress = True

    'バックグラウンド処理を開始する
    BackgroundWorker1.RunWorkerAsync()
End Sub

' 時間のかかる処理を実行する
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    For I As Integer = 1 To 100
        '200mSecスリープさせる
        System.Threading.Thread.Sleep(200)

        'ProgressChangedイベントを発生させる
        BackgroundWorker1.ReportProgress(I)
    Next
End Sub

' 進捗状況を更新する
Private Sub BackgroundWorker1_ProgressChanged(sender As System.Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    'プログレスバーを進捗させる
    ProgressBar1.Value = e.ProgressPercentage
End Sub

' バックグラウンド処理完了時の処理
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As System.Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    'バックグラウンド処理が完了したので[START]ボタンを有効にする
    btnStart.Enabled = True
End Sub

C#の例

// [START]ボタンクリック時の処理
private void btnStart_Click(object sender, EventArgs e)
{
    // [START]ボタンを無効にする
    btnStart.Enabled = false;

    // 進捗状況の報告をできるようにする
    backgroundWorker1.WorkerReportsProgress = true;

    // バックグラウンド処理を開始する
    backgroundWorker1.RunWorkerAsync();
}

// 時間のかかる処理を実行する
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 0; i < 100; i++)
    {
        // 200mSecスリープさせる
        System.Threading.Thread.Sleep(200);

        // ProgressChangedイベントを発生させる
        backgroundWorker1.ReportProgress(i + 1);
    }
}

// 進捗状況を更新する
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // プログレスバーを進捗させる
    progressBar1.Value = e.ProgressPercentage;
}

// バックグラウンド処理完了時の処理
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // バックグラウンド処理が完了したので[START]ボタンを有効にする
    btnStart.Enabled = true;
}