トップ回答者
ToolStripStatusLabel に表示データを送ってもデータの読み込み中は表示されない

質問
回答
すべての返信
-
Text プロパティに設定したからといってすぐに表示されるわけではありません。
読み込み処理でずっとそのイベントなり、メソッドなりの中にいるため、画面更新の処理が実行されていないのでしょう。
Refresh で効果があるかもしれませんが、長い処理をされる際は、別スレッド(ワーカースレッド)の導入を検討するべきです。
今のプログラムだと、「(応答なし)」とか表示されるかもしれません。
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
Application.DoEvents に頼らないでください。
処理中にもう一度処理を呼べる可能性があり、不具合を招くことが多いです。
今の処理がボタンによって実行されているようなケースの場合、Application.DoEvents によってもう一度ボタンイベントを起こせる可能性があります。
例えば、ボタンを2連打した場合、Application.DoEvents のタイミングで二度目のボタンのイベントハンドラが呼び出されることでしょう。
下記のようなサンプルで、Windows XP SP3 環境では処理終了までの間(End of work が出るまで)に Enter が2度出せると思います。(2連打で OK)
private void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("Enter!");
int sum = 0;
for (int i = 0; i < 100; i++)
{
sum += i;
Thread.Sleep(10);
}
button1.Text = "Sum" + sum;
Console.WriteLine("Sum" + sum);
sum = 0;
Application.DoEvents();
for (int i = 0; i < 200; i++)
{
sum += i;
Thread.Sleep(10);
}
button1.Text = "Sum" + sum;
Console.WriteLine("End of work");
}
質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。 -
Refresh するなら、コントロールである StatusStrip に対して行えばよいんですが、Control.Refresh() も Application.DoEvents() も、どちらも安易に利用するには危険な回避策であることは違いないので、Windows Forms の描画がどのようにして行われているのかといった基本を学んで、(スレッド処理等の) ロジックを見直すのが、よりベターな解決方法ですね。
Control.Refresh() と Application.DoEvents() は、共に「描画という目的を達成するために、並列して動作することを想定されていないコードを動かしてしまう可能性がある」という点が、危険性があとされています。2つのメソッドの差異は、太字にした部分の可能性が及ぶ範囲の違いだけです。特に、Applicatino.DoEvents() を気にされる場合が多いのは、その範囲が非常に広いためです。
最初に書いたように、Windows Forms の描画やメッセージハンドリングがどのように行われているかを有る程度理解し、Refresh や DoEvents によって発生しうる処理に問題がないことを確認しながら使う分には、問題がありません。
Application.DoEvents は、名前からわかるようにアプリケーション全体のイベント処理すべてに影響します。より、狭い範囲に影響を絞り込む意味で、Form の Refresh を利用すると、Form の描画処理にだけ影響するようになり、StatusStrip の Refresh であれば影響があるのはステータスバーの描画処理だけに限定することができます。通常、変なイベントハンドラを仕込んでいない限り、ステータスバーの描画処理は任意のタイミングで呼び出しても大丈夫なように作られているため、StatusStrip の Refresh メソッドはそれなりに安全に呼び出せることが期待できます。 -
K.Takaokaさんより
Control.Refresh() も Application.DoEvents() も、どちらも安易に利用するには危険な回避策であることは違いない
とのことで
実際は次のようにしました このまま正常に動作します
メインプログラム
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public System.Windows.Forms.StatusStrip statusStrip1;
public System.Windows.Forms.ToolStripProgressBar pb_進捗状況;
public Form1()
{
InitializeComponent();this.statusStrip1 = new System.Windows.Forms.StatusStrip();
this.pb_進捗状況 = new System.Windows.Forms.ToolStripProgressBar();
//
// statusStrip1
//
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.pb_進捗状況});
this.statusStrip1.Location = new System.Drawing.Point(0, 240);
this.statusStrip1.Name = "statusStrip1";
this.statusStrip1.Size = new System.Drawing.Size(390, 23);
this.statusStrip1.TabIndex = 0;
this.statusStrip1.Text = "statusStrip1";
//
// pb_進捗状況
//
this.pb_進捗状況.Name = "pb_進捗状況";
this.pb_進捗状況.Size = new System.Drawing.Size(100, 17);
this.Controls.Add(this.statusStrip1);
this.MouseClick += new MouseEventHandler(Form1_MouseClick);
}void Form1_MouseClick(object sender, MouseEventArgs e)
{
Form2 f状況報告Form2 = new Form2();
f状況報告Form2.Form1_親窓 = this;
f状況報告Form2.Show();
f状況報告Form2.l_状況報告.Text = "時間のかかる処理中";
f状況報告Form2.l_状況報告.Update();
pb_進捗状況.Maximum = 1000;
pb_進捗状況.Value = 1;for (int i = 0; i < 1000; i++)
{
for (int j = 0; j < 100000; j++)
{
pb_進捗状況.Value = i;
if (0 == i % 100)
{
f状況報告Form2.l_状況報告.Text = "時間のかかる処理中" + i.ToString();
f状況報告Form2.l_状況報告.Update();
}
}
}pb_進捗状況.Value = 0;
if (!f状況報告Form2.IsDisposed)
{
f状況報告Form2.Dispose();
}}
}
}
状況報告用プログラム
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace WindowsFormsApplication1
{
public partial class Form2 : Form
{
public Form1 Form1_親窓;
public Label l_状況報告 = new Label();public Form2()
{
InitializeComponent();//
// l_状況報告
//
l_状況報告.AutoSize = true;
l_状況報告.Location = new System.Drawing.Point(0, 1);
l_状況報告.Name = "l_状況報告";
l_状況報告.Size = new System.Drawing.Size(180, 20);
l_状況報告.TabIndex = 0;
l_状況報告.Text = "l_状況報告";
this.Load += new EventHandler(Form2_Load);
}void Form2_Load(object sender, EventArgs e)
{
FormBorderStyle = FormBorderStyle.None;
ClientSize = new Size(0, 0);
Location = new Point(0, 0);
Controls.Add(l_状況報告);
Layout += new LayoutEventHandler(Form2_Layout);
}void Form2_Layout(object sender, LayoutEventArgs e)
{
ClientSize = new Size(180, Form1_親窓.statusStrip1.Height - 6);
Location = new Point(
Form1_親窓.Location.X + Form1_親窓.pb_進捗状況.Size.Width + 13,
Form1_親窓.Location.Y + Form1_親窓.ClientSize.Height + 11);
}
}
}