BackgroundWorkerを使って実行中の別スレッドの処理をキャンセルする方法です。
(前節のサンプルにスレッドを停止する2つ目のボタンを追加しています)
まず準備として
BackgroundWorkerのWorkerSupportsCancellationプロパティーにtrueを設定し
このスレッドがキャンセルに対応することを設定します。
実際のキャンセル処理ですが
BackgroundWorkerのCancelAsync関数を任意のタイミングで呼び出します。
後は、DoWorkハンドラ内で定期的にキャンセルされていないか
CancellationPendingプロパティーを監視し、
CancellationPendingにtrueが設定されていれば
DoWorkEventArgs引数のCancelプロパティーにtrueを設定して
処理を中断(return)します。
処理が完了しても中断しても
最後はRunWorkerCompletedハンドラが呼ばれるので
そこでキャンセルによる停止なのか処理が完了したのか
理由を参照します。(e.Cancelled)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // RunWorkerAsyncが呼び出された時に発生 backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); // BackgroundWorkerでの処理が完了した時に発生 backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); // キャンセルされることを許可 backgroundWorker1.WorkerSupportsCancellation = true; } void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if(e.Cancelled) MessageBox.Show("処理はキャンセルされました"); else MessageBox.Show("処理完了"); } void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { for (int i = 0; i < 1000; i++) { // キャンセルされた? if (backgroundWorker1.CancellationPending) { e.Cancel = true; return; } System.Diagnostics.Debug.Write("@"); Application.DoEvents(); } } private void button1_Click(object sender, EventArgs e) { // BackgroundWorkerが処理中でなければ if (!backgroundWorker1.IsBusy) { // バックグラウンド処理を開始 backgroundWorker1.RunWorkerAsync(); for (int i = 0; i < 1000; i++) { System.Diagnostics.Debug.Write("_"); Application.DoEvents(); } } } private void button2_Click(object sender, EventArgs e) { // 処理をキャンセルします backgroundWorker1.CancelAsync(); } } }
コメントを残す