チュートリアル : 操作をバックグラウンドで実行する
更新 : 2007 年 11 月
完了するまでに時間がかかる操作があり、ユーザー インターフェイスが遅くならないようにする場合は、BackgroundWorker クラスを使用して別のスレッドで操作を実行できます。
ここで使用するコード例の完全なリストについては、「方法 : バックグラウンドで操作を実行する」を参照してください。
メモ : |
---|
使用している設定またはエディションによっては、表示されるダイアログ ボックスやメニュー コマンドがヘルプに記載されている内容と異なる場合があります。設定を変更するには、[ツール] メニューの [設定のインポートとエクスポート] をクリックします。詳細については、「Visual Studio の設定」を参照してください。 |
操作をバックグラウンドで実行するには
Windows フォーム デザイナでフォームをアクティブにした状態で、ツールボックスから 2 つの Button コントロールをフォームにドラッグし、ボタンの Name プロパティおよび Text プロパティを以下の表のとおりに設定します。
ボタン
名前
テキスト
button1
startBtn
[開始]
button2
cancelBtn
[キャンセル]
ツールボックスを開き、[コンポーネント] タブをクリックします。次に、BackgroundWorker コンポーネントをフォームにドラッグします。
backgroundWorker1 コンポーネントが、コンポーネント トレイに表示されます。
[プロパティ] ウィンドウの [イベント] ボタンをクリックし、DoWork イベントおよび RunWorkerCompleted イベントをダブルクリックしてイベント ハンドラを作成します。
完了するまでに時間のかかるコードを DoWork イベント ハンドラに挿入します。
操作に必要なパラメータを DoWorkEventArgs パラメータの Argument プロパティから抽出します。
計算の結果を DoWorkEventArgs の Result プロパティに代入します。
この値は、RunWorkerCompleted イベント ハンドラで使用できます。
Private Sub backgroundWorker1_DoWork( _ sender As Object, e As DoWorkEventArgs) _ Handles backgroundWorker1.DoWork ' Do not access the form's BackgroundWorker reference directly. ' Instead, use the reference provided by the sender parameter. Dim bw As BackgroundWorker = CType( sender, BackgroundWorker ) ' Extract the argument. Dim arg As Integer = Fix(e.Argument) ' Start the time-consuming operation. e.Result = TimeConsumingOperation(bw, arg) ' If the operation was canceled by the user, ' set the DoWorkEventArgs.Cancel property to true. If bw.CancellationPending Then e.Cancel = True End If End Sub
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { // Do not access the form's BackgroundWorker reference directly. // Instead, use the reference provided by the sender parameter. BackgroundWorker bw = sender as BackgroundWorker; // Extract the argument. int arg = (int)e.Argument; // Start the time-consuming operation. e.Result = TimeConsumingOperation(bw, arg); // If the operation was canceled by the user, // set the DoWorkEventArgs.Cancel property to true. if (bw.CancellationPending) { e.Cancel = true; } }
操作の結果を取得するコードを RunWorkerCompleted イベント ハンドラに挿入します。
' This event handler demonstrates how to interpret ' the outcome of the asynchronous operation implemented ' in the DoWork event handler. Private Sub backgroundWorker1_RunWorkerCompleted( _ sender As Object, e As RunWorkerCompletedEventArgs) _ Handles backgroundWorker1.RunWorkerCompleted If e.Cancelled Then ' The user canceled the operation. MessageBox.Show("Operation was canceled") ElseIf (e.Error IsNot Nothing) Then ' There was an error during the operation. Dim msg As String = String.Format("An error occurred: {0}", e.Error.Message) MessageBox.Show(msg) Else ' The operation completed normally. Dim msg As String = String.Format("Result = {0}", e.Result) MessageBox.Show(msg) End If End Sub
// This event handler demonstrates how to interpret // the outcome of the asynchronous operation implemented // in the DoWork event handler. private void backgroundWorker1_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { // The user canceled the operation. MessageBox.Show("Operation was canceled"); } else if (e.Error != null) { // There was an error during the operation. string msg = String.Format("An error occurred: {0}", e.Error.Message); MessageBox.Show(msg); } else { // The operation completed normally. string msg = String.Format("Result = {0}", e.Result); MessageBox.Show(msg); } }
TimeConsumingOperation メソッドを実装します。
' This method models an operation that may take a long time ' to run. It can be cancelled, it can raise an exception, ' or it can exit normally and return a result. These outcomes ' are chosen randomly. Private Function TimeConsumingOperation( _ bw As BackgroundWorker, _ sleepPeriod As Integer) As Integer Dim result As Integer = 0 Dim rand As New Random() While Not bw.CancellationPending Dim [exit] As Boolean = False Select Case rand.Next(3) ' Raise an exception. Case 0 Throw New Exception("An error condition occurred.") Exit While ' Sleep for the number of milliseconds ' specified by the sleepPeriod parameter. Case 1 Thread.Sleep(sleepPeriod) Exit While ' Exit and return normally. Case 2 result = 23 [exit] = True Exit While Case Else Exit While End Select If [exit] Then Exit While End If End While Return result End Function
// This method models an operation that may take a long time // to run. It can be cancelled, it can raise an exception, // or it can exit normally and return a result. These outcomes // are chosen randomly. private int TimeConsumingOperation( BackgroundWorker bw, int sleepPeriod ) { int result = 0; Random rand = new Random(); while (!bw.CancellationPending) { bool exit = false; switch (rand.Next(3)) { // Raise an exception. case 0: { throw new Exception("An error condition occurred."); break; } // Sleep for the number of milliseconds // specified by the sleepPeriod parameter. case 1: { Thread.Sleep(sleepPeriod); break; } // Exit and return normally. case 2: { result = 23; exit = true; break; } default: { break; } } if( exit ) { break; } } return result; }
Windows フォーム デザイナで startButton をダブルクリックして Click イベント ハンドラを作成します。
startButton の Click イベント ハンドラで RunWorkerAsync メソッドを呼び出します。
Private Sub startButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles startBtn.Click Me.backgroundWorker1.RunWorkerAsync(2000) End Sub
private void startBtn_Click(object sender, EventArgs e) { this.backgroundWorker1.RunWorkerAsync(2000); }
Windows フォーム デザイナで cancelButton をダブルクリックして Click イベント ハンドラを作成します。
cancelButton の Click イベント ハンドラでCancelAsync メソッドを呼び出します。
Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles cancelBtn.Click Me.backgroundWorker1.CancelAsync() End Sub
private void cancelBtn_Click(object sender, EventArgs e) { this.backgroundWorker1.CancelAsync(); }
ファイルの先頭に System.ComponentModel and System.Threading 名前空間をインポートします。
Imports System Imports System.ComponentModel Imports System.Drawing Imports System.Threading Imports System.Windows.Forms
using System; using System.ComponentModel; using System.Drawing; using System.Threading; using System.Windows.Forms;
F6 を押してソリューションをビルドした後で、Ctrl キーを押しながら F5 キーを押してアプリケーションをデバッガの外部で実行します。
メモ : |
---|
F5 キーを押してアプリケーションをデバッガの内部で実行した場合、TimeConsumingOperation メソッド内で発生する例外がデバッガにキャッチされ、表示されます。アプリケーションをデバッガの外部で実行すると、BackgroundWorker が例外を処理し、RunWorkerCompletedEventArgs の Error プロパティにキャッシュします。 |
非同期操作を実行するには [開始] をクリックし、非同期操作の実行を停止するには [キャンセル] をクリックします。
各操作の結果は、MessageBox に表示されます。
次の手順
非同期操作の進行状況を通知するフォームを実装します。詳細については、「方法 : バックグラウンド操作を使用するフォームを実装する」を参照してください。
コンポーネント向けの非同期パターンをサポートするクラスを実装します。詳細については、「イベントベースの非同期パターンの実装」を参照してください。