CodePanic! > C#.NET Tips > 今ここ
■スレッドの処理を途中で停止、キャンセルする
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();
}
}
}
Copyright © 2008.07 - shougo suzaki
|