.NET TIPS 時間のかかる処理をバックグラウンドで実行するには?[2.0のみ、C#、VB]デジタルアドバンテージ 遠藤 孝信2006/04/14 |
|
|
Windowsアプリケーションでは、時間のかかる処理(以下、重い処理)はアプリケーションのメインのスレッドとは別のスレッドで行わなければならない。これは重い処理がアプリケーションのユーザー・インターフェイス(UI)をフリーズさせてしまうからだ。
たとえユーザーがその処理の完了まで待つ必要があるとしても、その間にウィンドウの移動や最小化ができなければならないし、可能であれば処理の進ちょく状況をプログレス・バーなどで表示すべきである。
.NET Framework 2.0では、そのような処理を容易に実装するための「BackgroundWorkerコンポーネント」が新しく追加されている。これを使えばスレッドをほとんど意識することなく、重い処理を別スレッド(バックグラウンド)で実行させることができる。
本稿では、BackgroundWorkerコンポーネントを利用し、進ちょく状況を表示しながら、重い処理をバックグラウンドで実行するための方法について解説する。
なおBackgroundWorkerコンポーネントでは、バックグラウンドの処理をキャンセルして途中で中止することもできる。これについては別稿「TIPS:バックグラウンド処理を途中でキャンセルするには?」で解説しているので併せて参照していただきたい。
BackgroundWorkerコンポーネントの配置
以下では、Visual Studio 2005でサンプル・アプリケーションを作成しながらBackgroundWorkerコンポーネントの使い方について説明していく。
まず、Windowsアプリケーションのプロジェクトを新規作成し、以下の画面のように[スタート]ボタンとProgressBarコントロール、そしてBackgroundWorkerコンポーネントを配置する。そしてプロパティ・ウィンドウで、それぞれのNameプロパティを「startButton」「progressBar」「bgWorker」に設定する。
BackgroundWorkerコンポーネントを配置したWindowsフォーム |
進ちょく状況を表示するためには、BackgroundWorkerコンポーネントのWorkerReportsProgressプロパティをtrueに設定しておく。 |
さらにBackgroundWorkerコンポーネントについては、進ちょく状況を表示するためにWorkerReportsProgressプロパティをtrueに設定する。
このサンプル・プログラムでは、[スタート]ボタンがクリックされると、重い処理を開始し、その進ちょく状況をProgressBarコントロールのバーと、タイトルバーの文字で示す。また、処理完了時にはメッセージボックスを表示する。
BackgroundWorkerコンポーネントの動作
BackgroundWorkerコンポーネントに対しては、次の3つのイベント・ハンドラの追加が必要となる(詳細は割愛するが、イベント・ハンドラの追加はC#ではプロパティ・ウィンドウから、VBではコード画面上部から簡単に行える)。
重い処理を行うDoWorkイベント・ハンドラ(別スレッドで実行される)
進ちょく状況を表示するためのProgressChangedイベント・ハンドラ
処理完了時に実行されるRunWorkerCompletedイベント・ハンドラ
重い処理の実行開始から処理完了までの流れは次のようになる。
- BackgroundWorkerコンポーネントのRunWorkerAsyncメソッドを呼び出すことにより、
が実行される。このときにパラメータを渡せば、
では「e. Argument」*1として受け取ることができる。
-
の重い処理の間にBackgroundWorkerコンポーネントのReportProgressメソッドを適時呼び出すことにより、
が実行される。メソッドのパラメータには進ちょく状況を示す整数値を指定する。
では「e. ProgressPercentage」*2により、この値を受け取ることができる。
- の重い処理が完了すれば(イベント・ハンドラの実行が終了すれば)、 が実行される。 で処理結果を「e.Result」*3に代入しておけば、 で「e.Result」*4によりその値を受け取ることができる。
*1 「e」はDoWorkEventArgsクラスのオブジェクト。 *2 「e」はProgressChangedEventArgsクラスのオブジェクト。 *3 「e」はDoWorkEventArgsクラスのオブジェクト。 *4 「e」はRunWorkerCompletedEventArgsクラスのオブジェクト。 ※ いずれのクラスもSystem.ComponentModel名前空間に属する。 |
サンプル・アプリケーションのソース・コード
今回のサンプル・プログラムでは、[スタート]ボタンのClickイベント・ハンドラで、RunWorkerAsyncメソッドを呼び出して、 のDoWorkイベント・ハンドラの実行を開始する。
また、 のProgressChangedイベント・ハンドラでは、ProgressBarコントロールのValueプロパティに進ちょく率を示す値を代入してバーの更新を行う。
以下に、サンプル・アプリケーションのソース・コードを示す(Form1.cs/Form1.vbのみ。ソリューション全体はリストの脚注からダウンロード可)。
|
||
進ちょく状況を表示しながら重い処理を行うサンプル・プログラム(上:Form1.cs、下:Form1.vb) | ||
注意すべきは、DoWorkイベント・ハンドラだけは別スレッドで実行されるため、そのメソッド内でコントロールのプロパティやメソッドを操作してはいけないという点だ(そのような操作を行うと.NET Framework 2.0では例外が発生する)。
また、DoWorkイベント・ハンドラ実行中に、さらにRunWorkerAsyncメソッドを呼び出すことはできない(例外が発生する)。それが実行中かどうかはIsBusyプロパティにより確認できる。今回のサンプル・プログラムでは、ボタンの有効/無効を切り替えて多重な実行を禁止している。
利用可能バージョン:.NET Framework 2.0のみ カテゴリ:Windowsフォーム 処理対象:スレッド 使用ライブラリ:BackgroundWorkerコンポーネント(System.ComponentModel名前空間) 使用ライブラリ:DoWorkEventArgsクラス(System.ComponentModel名前空間) 使用ライブラリ:ProgressChangedEventArgsクラス(System.ComponentModel名前空間) 使用ライブラリ:RunWorkerCompletedEventArgsクラス(System.ComponentModel名前空間) 関連TIPS:バックグラウンド処理を途中でキャンセルするには? |
「.NET TIPS」 |
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|