none
ToolStripStatusLabel に表示データを送ってもデータの読み込み中は表示されない RRS feed

  • 質問


  • ToolStripStatusLabel に表示データを送ってもデータの読み込み中は表示されない

            public System.Windows.Forms.ToolStripStatusLabel lb_状況報告;

        データ読み込みA
            {
                     lb_状況報告.Text="データ読み込みA";
            }
        データ読み込みB
            {
                     lb_状況報告.Text="データ読み込みB";
            }

    データ読み込みA と データ読み込みB と実行された場合

        lb_状況報告.Text="データ読み込みA";

    は表示されません
    どうすれば表示されるようになりますか?

    2010年2月17日 6:31

回答

  • > Refresh 関数 はないので実行できない
    なるほど…では
    Application.DoEvents();
    を入れるとどうでしょうか?

    Application.DoEvents メソッド
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.application.doevents(VS.80).aspx
    • 回答としてマーク 本松 2010年2月17日 20:23
    2010年2月17日 19:38

すべての返信

  • lb_状況報告.Text="データ読み込みA";
    の下に
    lb_状況報告.Refresh();
    を入れるとどうですか?
    2010年2月17日 6:50
  • Text プロパティに設定したからといってすぐに表示されるわけではありません。
    読み込み処理でずっとそのイベントなり、メソッドなりの中にいるため、画面更新の処理が実行されていないのでしょう。

    Refresh で効果があるかもしれませんが、長い処理をされる際は、別スレッド(ワーカースレッド)の導入を検討するべきです。
    今のプログラムだと、「(応答なし)」とか表示されるかもしれません。


    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年2月17日 14:13
    モデレータ
  • Microsoft Visual Studio 2008 C# の ToolStripStatusLabel に Refresh 関数 はないので実行できない
     
    2010年2月17日 17:13
  • Microsoft Visual Studio 2008 C# の ToolStripStatusLabel に
    Refresh 関数 はないので実行できない
    Update 関数も使えない
    Invalidate 関数も効果なし

    後は(BackgroundWorker)によるバックグラウンド処理みたいな方法しかないのでしょうか?

    2010年2月17日 17:25
  • > Refresh 関数 はないので実行できない
    なるほど…では
    Application.DoEvents();
    を入れるとどうでしょうか?

    Application.DoEvents メソッド
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.application.doevents(VS.80).aspx
    • 回答としてマーク 本松 2010年2月17日 20:23
    2010年2月17日 19:38
  • Application.DoEvents();
    でうまくいきました。
    ありがとうございます。
    2010年2月17日 20:23
  • 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");
    }



    質問スレッドで解決した場合は、解決の参考になった投稿に対して「回答としてマーク」のボタンを押すことで、同じ問題に遭遇した別のユーザが役立つ投稿を見つけやすくなります。
    2010年2月17日 22:51
    モデレータ
  • 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 メソッドはそれなりに安全に呼び出せることが期待できます。

    2010年2月19日 4:08
  • 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);
            }
        }
    }

    2010年3月5日 5:31