つい先ほど
書いた処理ですが、あまりに重たかったので、実行中であることを知らしめるためのウィンドウが欲しくなりました。
以下のような感じで使えたら便利です。
public void 重たい処理() {
using (Running running = new Running()) {
running.OpenWindow();
for (int i = int.MinValue; i < int.MaxValue; ++i) {}
running.CloseWindow();
}
}
実際の話、先に呼び出す側を上記のように作ってしまったので、本体を後から作ることになりました。
(本日のブログは、リアルタイムでお送りしておりますw)
こういう場合、マルチスレッドにするのが良さそうですが、この手の処理は頻繁に起こりそうですし、手軽に使えるものが欲しかったので、下記のように簡単なものにしてみました。
using System.Windows.Forms;
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 void OpenWindow() {
this.Show(); // 実際に、ウィンドウが表示されたわけではない。
}
public void CloseWindow() {
this.Close();
}
}
しかし、単に、Show() すれば良いのかと思っていたのですが、処理のタイミングの問題で、ウィンドウの表示前に重たい処理に突入されてしまいました。
そして、この結果、重い処理が終わった後に、実行中ウィンドウが一瞬表示された落ちましたorz
(スプラッシュウィンドウの時に Jitta さんが仰っていましたね)
そこで、Shown イベントでウィンドウが表示されるのを待つようにしたのが以下のコードです。
public partial class Running : Form
{
private bool ShownFlag;
public Running() {
this.ControlBox = false;
this.FormBorderStyle = FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Running";
this.StartPosition = FormStartPosition.CenterScreen;
this.Text = "実行中";
this.TopMost = true;
this.Shown += new System.EventHandler(this.Running_Shown);
}
public void OpenWindow() {
this.ShownFlag = false;
this.Show();
while (! this.ShownFlag) {
Application.DoEvents(); // ここのループがちょっと怖い。
}
}
public void CloseWindow() {
this.Close();
}
private void Running_Shown(object sender, EventArgs e) {
this.ShownFlag = true;
}
}
これなら、ウィンドウが表示されてから、OpenWindows() メソッドが終了するので無事に開いてくれました。
後は、このフォームにメッセージとかアニメーションとかプログレスバーを付けたり、適当なプロパティを実装すれば、それなりのものになるでしょう。
ただ、重い処理の部分では、Application.DoEvents() 噛まさないといけません。
処理速度を高速にするなら、やはりマルチスレッドということになるのでしょうか?