インスタンスを生成します。
BackgroundWorker bw = new BackgroundWorker();
ここからは「bw」という名前で生成したインスタンスを使い、話を進めます。
バックグラウンド処理を実行する
DoWork
イベントにバックグラウンドで行う処理(イベントハンドラ)をフックします。
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
バックグラウンド処理を実行する。
bw.RunWorkerAsync();
引数を渡す場合の例)
bw.RunWorkerAsync(100);
DoWork
イベントハンドラ内で渡された引数を使用する例)
int arg = (int)e.Argument;
DoWork
イベントハンドラの例)
void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
int i = 0, count = (int)e.Argument;
while (i < count)
{
Thread.Sleep(100);
bw.ReportProgress(++i);
if (bw.CancellationPending)
{
e.Cancel = true;
break;
}
}
}
処理をキャンセルする
BackgroundWorker
が非同期のキャンセルをサポートしているかどうかを示す値を設定します。
bw.WorkerSupportsCancellation = true;
キャンセルを要求します。
bw.CancelAsync();
CancellationPending
プロパティが
true
に設定されます。
処理がキャンセルされたかを
DoWork
イベントハンドラ内で
CancellationPending
プロパティを定期的にチェックする必要があります。
例)
BackgroundWorker worker = sender as BackgroundWorker;
if(worker.CancellationPending)
{
//e.Cancel = true;
}
処理がキャンセルされた場合、
RunWorkerCompleted
イベントで処理がキャンセルされたことを知らせるには
DoWork
イベントハンドラ内で以下の処理を行います。
e.Cancel = true;
RunWorkerCompleted
イベントにフックしたイベントハンドラで処理がキャンセルされたかどうかを取得する例を示します。
if (e.Cancelled) {
MessageBox.Show("キャンセルされました。");
}
キャンセルの流れ
bw.CancelAsync()
↓
DoWork
イベントハンドラにて
worker.CancellationPending
プロパティがtrue
になる。
↓
キャンセルされたことを知らせるため
e.Cancel = true
とする。
↓
処理を中断する。
↓
RunWorkerCompleted
イベントハンドラにて
e.Cancelled
プロパティがtrue
になっている。
進行状況の更新
進行状況の更新を報告できるように設定します。
bw.WorkerReportsProgress = true;
ProgressChanged
イベントにフックします。
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
ProgressChanged
イベントにフックするイベントハンドラの例)
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
ProgressChanged
イベントハンドラ内ではメインスレッドのコントロールにアクセス可能です。
進捗状況を更新します。
worker.ReportProgress(progressPercentage);
ReportProgress
メソッドを実行すると
ProgressChanged
イベントが発生します。
このメソッドの引数として渡した値が
ProgressChanged
イベントにフックしたイベントハンドラで
e.ProgressPercentage
として受け取ることができます。
他の引数を一つ渡すことが出来ます。
worker.ReportProgress(progressPercentage, "Working...");
Sample Code
public partial class Form1 : Form
{
BackgroundWorker bw;
public Form1()
{
InitializeComponent();
progressBar1.Maximum = 100;
bw = new BackgroundWorker();
//BackgroundWorker が非同期のキャンセルをサポートしているかどうかを
//示す値を取得または設定します。
bw.WorkerSupportsCancellation = true;
//プログレスバー関連
//BackgroundWorker が進行状況の更新を報告できるかどうかを示す値を取得または設定します。
bw.WorkerReportsProgress = true;
//ReportProgress が呼び出されたときに発生します。
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
//RunWorkerAsync が呼び出されたときに発生します。
//実際にバックグラウンド処理を行うイベントハンドラ
//イベントにフックする。
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
//バックグラウンド操作の完了時、キャンセル時、
//またはバックグラウンド操作によって例外が発生したときに発生します。
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}
private void btnExec_Click(object sender, EventArgs e)
{
//IsBusy - BackgroundWorker が非同期操作を実行中かどうかを示す値を取得します。
if (!bw.IsBusy)
{
//バックグラウンド操作の実行を開始します。
bw.RunWorkerAsync(100);
}
}
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressBar1.Value = e.ProgressPercentage;
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
int i = 0, count = (int)e.Argument;
while (i < count)
{
Thread.Sleep(50);
bw.ReportProgress(++i);
if (bw.CancellationPending)
{
e.Cancel = true;
break;
}
}
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
string msg = string.Empty;
if (e.Cancelled)
{
msg = "Cancelled";
}
else
{
msg = "Done";
}
MessageBox.Show(msg);
progressBar1.Value = 0;
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (bw.IsBusy)
{
bw.CancelAsync();
}
}
}