簡単な実行中ウィンドウ(その1)
http://blogs.wankuma.com/rti/archive/2007/01/23/57920.aspx
前回、単一のスレッドだけで実行中ウィンドウを実現してみました。
この時、あまりにも BackgroundWorker と言われ続けたので、今回は、BackgroundWorker を使って、実行中ウィンドウの表示と共に、別スレッドで重たい処理を行ってみました。
using System.Windows.Forms;
using System.ComponentModel;
予め上記の名前空間を using で指定しておきます。今回の主役 BackgroundWorker は System.ComponentModel 名前空間に所属しています。
まずは実行中ウィンドウです。
今回は、重い処理は別スレッドで行うので、前回のようないろいろな細工は不要です。
これは BackgroundWorker の最大の利点です。
public partial class Running : Form
{
public Running() {
this.ControlBox = false;
// キャンセル処理書くの面倒くさい
this.FormBorderStyle = FormBorderStyle.FixedSingle;
// サイズは変更させない。
this.MaximizeBox = false;
this.MinimizeBox = false;
this.StartPosition = FormStartPosition.CenterScreen;
// ど真ん中 this.TopMost = true;
// 手前に表示
this.Text = "実行中";
}
public int
Progress() {
get {
return this._Progress;
}
set {
this._Progress = value;
}
}
}
なお、実行中フォームには、進捗具合を受け取るプロパティを付けてあります。
このプロパティは、進捗具合を表現させるために自由に使えば良いでしょう。
次が処理本体です。
わかりやすくするために、オブジェクト名を日本語にしています。
public partial class 簡単な実行中ウィンドウ2
{
private RunningForm 実行中;
private BackgroundWorker 裏方作業;
public 簡単な実行中ウィンドウ2() {
this.実行中 = new RunningForm();
this.裏方作業 = new BackgroundWorker();
this.裏方作業.DoWork += new DoWorkEventHandler(
this.裏方作業_DoWork
);
this.裏方作業.RunWorkerCompleted += new RunWorkerCompletedEventHandler(
this.裏方作業_RunWorkerCompleted
);
this.裏方作業.ProgressChanged += new ProgressChangedEventHandler(
this.裏方作業_ProgressChanged
);
// 裏方作業の進捗報告をする(しない方が高速)
this.裏方作業.WorkerReportsProgress = true;
}
public void 重たい処理を開始する() {
this.実行中.Show();
// 裏方作業開始(裏方作業_DoWork を呼び出す)
this.裏方作業.RunWorkerAsync();
}
private void 重たい処理本体() {
for (int i = 0; i < int.MaxValue; ++i) {
// 裏方作業具合を報告(裏方作業_ProgressChanged を呼び出す)
裏方作業.ReportProgress(i);
}
// この処理が終わったら、裏方作業_RunWorkerCompletedが
// 呼び出される。
}
private void 裏方作業_DoWork(object sender, DoWorkEventArgs e) {
// 裏方作業で重たい処理を実行する。
this.重たい処理本体();
}
private void 裏方作業_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
実行中.Close(); // 裏方作業が終わったので実行中を閉じる。
}
private void 裏方作業_ProgressChanged(object sender, ProgressChangedEventArgs e) {
// 実行中に裏方作業具合を渡す。
実行中.Progress = e.ProgressPercentage;
}
}
イベントが絡むので処理の順番が把握しにくいですが、この分コメントを細かく入れたので確認してみて下さい。
ちなみに
裏方作業
というオブジェクト名は、かなり気に入っています。
public void 重たい処理を開始する() {
this.実行中.Show();
// 裏方作業開始(裏方作業_DoWork を呼び出す)
this.裏方作業.RunWorkerAsync();
}
特に、上記の部分の処理に着目して欲しいのですが、RunWorkerAsync() メソッドによって、重い処理が開始されます。
ちょっとわかりにくいかもしれませんが、シングルスレッドで実行している場合は、Show() した実行中フォームの表示がきちんと完了されていない状態で、重たい処理が行われてしまうという可能性があります。
こうなると、重たい処理が終了してから実行中フォームが画面に一瞬表示されて消えるというような動作になることも珍しくありません。
しかし、今回は重い処理を別のスレッドで実行しているため、この心配は不要になります。