[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;
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です