R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

簡単な実行中ウィンドウ(その1)

つい先ほど

書いた処理ですが、あまりに重たかったので、実行中であることを知らしめるためのウィンドウが欲しくなりました。

以下のような感じで使えたら便利です。

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() 噛まさないといけません。
処理速度を高速にするなら、やはりマルチスレッドということになるのでしょうか?

投稿日時 : 2007年1月23日 16:44

Feedback

# re: 簡単な実行中ウィンドウ 2007/01/23 17:03 中博俊

See BackgroundWorker

# re: 簡単な実行中ウィンドウ 2007/01/23 17:11 R・田中一郎

これですね!
http://www.microsoft.com/japan/msdn/vs05/vbasic/threadinginvb2005.aspx

# re: 簡単な実行中ウィンドウ 2007/01/23 17:20 ぽぴ王子

やあ、僕はキャプテントーマス。正しいみんなの友達さ(声・大塚芳忠)

キャプテンも以前そんな風にコーディングしてたんだけど、ボタンを連打していたら Application.DoEvents() の処理中にクリック処理が走ってしまって大変だったのさ。
そんなときは this.Update() これだね!

これで大丈夫。地球も大喜びさ♪
(元ネタは「神聖モテモテ王国」でググれ)

# re: 簡単な実行中ウィンドウ 2007/01/23 17:29 R・田中一郎

>そんなときは this.Update() これだね!

以前見かけたことがあったのに、すっかり存在を忘れていました^^;
ありがとうございます。

# re: 簡単な実行中ウィンドウ 2007/01/24 10:11 渋木宏明(ひどり)

this.Update() は最後の武器。
BackgroundWorker を使う方がいいと思いマス。

# re: 簡単な実行中ウィンドウ 2007/01/24 11:28 R・田中一郎

渋木宏明(ひどり) さん

>BackgroundWorker を使う方がいいと思いマス。

了解です。
素直に、そうしようと思います。

# re: 簡単な実行中ウィンドウ 2007/01/24 14:56 ぽぴ王子

> this.Update() は最後の武器。

そうですね。我々は忍者部隊でした(違
…って、みんなついてこれてますカー?

僕が…もといキャプテン・トーマスが Update() を使ったのは、フォアグラウンド(のスレッド)でという指定があったからでした。そして Application.DoEvents() を使って玉砕したらしいのです。
そんな縛りがなければ、最初から BackgroundWorker を使うなり、自分でスレッドを立ち上げるなりしてただろうという話でした。

# re: 簡単な実行中ウィンドウ 2007/01/24 15:41 R・田中一郎

>でという指定があったからでした。そして Application.DoEvents() を使って玉砕したらしいのです

やっぱりそうなるのか・・・
最初から素直に、スレッド分ければ良かった orz

# 簡単な実行中ウィンドウ(その2) 2007/02/07 14:43 R.Tanaka.Ichiro's Blog

簡単な実行中ウィンドウ(その2)

# 簡単な実行中ウィンドウ(その2) 2007/02/07 14:44 R.Tanaka.Ichiro's Blog

簡単な実行中ウィンドウ(その2)

# Such a deep aneswr! GD&RVVF 2012/01/29 3:59 Summer

Such a deep aneswr! GD&RVVF

# Such a deep aneswr! GD&RVVF 2012/01/29 4:00 Summer

Such a deep aneswr! GD&RVVF

# Such a deep aneswr! GD&RVVF 2012/01/29 4:00 Summer

Such a deep aneswr! GD&RVVF

タイトル
名前
Url
コメント