BackgroundWorker コンポーネントの概要
一般的な操作には、実行時間が長くかかるものが数多くあります。 たとえば、次のような操作です。
イメージのダウンロード
Web サービスの起動
ファイルのダウンロードとアップロード (ピアツーピア アプリケーションの場合を含む)
ローカルでの複雑な計算
データベース トランザクション
ローカル ディスク アクセス (前提としてメモリ アクセスに比べて低速です)
以上のような操作の実行時には、ユーザー インターフェイスがハングアップすることがあります。 応答性に優れたインターフェイスを必要としながらも、このような操作との関連で長時間の遅延に直面する場合は、BackgroundWorker コンポーネントが便利なソリューションになります。
BackgroundWorker コンポーネントを使用すると、時間のかかる操作を、アプリケーションのメイン UI スレッドとは別のスレッドで非同期的に ("バックグラウンドで") 実行できます。 BackgroundWorker を使用するには、バックグラウンドで実行する、時間のかかるワーカー メソッドをこのコンポーネントに通知して、RunWorkerAsync メソッドを呼び出すだけです。 呼び出し元スレッドが正常に動作し続けると共に、ワーカー メソッドも非同期的に動作します。 このメソッドが終了すると、BackgroundWorker は、RunWorkerCompleted イベントを起動して、呼び出し元スレッドに警告します。このイベントには、オプションで操作の結果を含めることもできます。
BackgroundWorker コンポーネントは、[コンポーネント] タブの [ツールボックス] で選択できます。 BackgroundWorker をフォームに追加するには、BackgroundWorker コンポーネントをフォームにドラッグします。 このコンポーネントはコンポーネント トレイに表示され、プロパティが [プロパティ] ウィンドウに表示されます。
非同期操作を開始するには、RunWorkerAsync メソッドを使用します。 RunWorkerAsync は、オプションの object パラメーターを受け取り、このパラメーターを使用してワーカー メソッドに引数を渡すことができます。 BackgroundWorker クラスは、DoWork イベントを公開します。このイベントには、DoWork イベント ハンドラー経由でワーカー スレッドをアタッチします。
DoWork イベント ハンドラーは、Argument プロパティを持つ DoWorkEventArgs パラメーターを受け取ります。 このプロパティは、RunWorkerAsync からパラメーターを受け取り、DoWork イベント ハンドラーで呼び出されるワーカー メソッドに渡されます。 次の例は、ComputeFibonacci というワーカー メソッドの結果を代入する方法を示しています。 これは、「方法 : バックグラウンド操作を使用するフォームを実装する」に記載されている例の一部です。
' This event handler is where the actual work is done.
Private Sub backgroundWorker1_DoWork( _
ByVal sender As Object, _
ByVal e As DoWorkEventArgs) _
Handles backgroundWorker1.DoWork
' Get the BackgroundWorker object that raised this event.
Dim worker As BackgroundWorker = _
CType(sender, BackgroundWorker)
' Assign the result of the computation
' to the Result property of the DoWorkEventArgs
' object. This is will be available to the
' RunWorkerCompleted eventhandler.
e.Result = ComputeFibonacci(e.Argument, worker, e)
End Sub 'backgroundWorker1_DoWork
// This event handler is where the actual,
// potentially time-consuming work is done.
private void backgroundWorker1_DoWork(object sender,
DoWorkEventArgs e)
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker worker = sender as BackgroundWorker;
// Assign the result of the computation
// to the Result property of the DoWorkEventArgs
// object. This is will be available to the
// RunWorkerCompleted eventhandler.
e.Result = ComputeFibonacci((int)e.Argument, worker, e);
}
// This event handler is where the actual,
// potentially time-consuming work is done.
void backgroundWorker1_DoWork( Object^ sender, DoWorkEventArgs^ e )
{
// Get the BackgroundWorker that raised this event.
BackgroundWorker^ worker = dynamic_cast<BackgroundWorker^>(sender);
// Assign the result of the computation
// to the Result property of the DoWorkEventArgs
// object. This is will be available to the
// RunWorkerCompleted eventhandler.
e->Result = ComputeFibonacci( safe_cast<Int32>(e->Argument), worker, e );
}
イベント ハンドラーの使い方の詳細については、「イベントとデリゲート」を参照してください。
ヒント
どのような種類のマルチスレッドを使用している場合でも、非常に深刻で複雑なバグを引き起こしてしまう可能性があります。 マルチスレッドを使用するソリューションを実装する前に、「マネージ スレッド処理の実施」を参照してください。
BackgroundWorker クラスの使い方の詳細については、「方法 : バックグラウンドで操作を実行する」を参照してください。