0

I have this code:

namespace TuyenTk
{
    public partial class Form1 : Form
    {
        Form2 _form2 = new Form2("");
        public Form1()
        {
            InitializeComponent();
            _form2.Show();
            int i = 0;
            while (i < 5)
            {
                _form2.label1.Text = "" + i;
                Thread.Sleep(500);
                i++;
            }
        }
    }

    public class Form2 : Form
    {
        public System.Windows.Forms.Label label1;
        public System.ComponentModel.Container components = null;

        public Form2()
        {
            InitializeComponent();
        }
        private void InitializeComponent(string t)
        {
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.Location = new System.Drawing.Point(5, 5);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(290, 100);
            this.label1.TabIndex = 0;
            this.label1.Text = t;
            // 
            // Form2
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(300, 100);
            this.ControlBox = false;
            this.Controls.Add(this.label1);
            this.Name = "Form2";
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
            this.ShowInTaskbar = false;
            this.ResumeLayout(false);    
        }
    }
}

when Form1 run, it show the Form2, but the Form2.label1 background is white, and have no text.
After 2.5 seconds, Form2.label1.Text = 4. So the value 0, 1, 2, 3 of i dont appear. How I can fix it? Thank you very much.

NoName
  • 7,940
  • 13
  • 56
  • 108
  • Adding _form2.label1.Update(); would be a workaround. Don't write code like this, sleeping the UI thread is *always* a bad idea. – Hans Passant Dec 08 '12 at 16:07

2 Answers2

3

What you want to do (periodically update label) is achieved by usage of Timer component (you can drag it from ToolBox and place on your form).

public partial class Form1 : Form
{
   Form2 _form2 = new Form2("");
   Timer _timer;
   int _counter;

   public Form1()
   {
       InitializeComponent();          
       _form2.Show();

       if (components == null)
           components = new System.ComponentModel.Container();
       _timer = new Timer(components); // required for correct disposing

       _timer.Interval = 500;
       _timer.Tick += timer_Tick;
       _timer.Start();
   }

   private void timer_Tick(object sender, EventArgs e)
   {
       if (_counter < 5)
       {
          _form2.label1.Text = _counter.ToString();
          _counter++;
          return;
       }

       _timer.Stop();
   }

Also creating public controls on other forms is not very good idea - if you really need to update some value on form2, then its better to declare public method/property in Form2 class, which will update label:

public partial class Form2 : Form
{
     public int Value
     {             
         set { label1.Text = value.ToString(); }
     }
}

Also consider to move timer to Form2 (let this form update itself).

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • Using the toolbox was good advice. The code is not, a timer needs to be disposed if you create one like this. It will keep ticking after the user closes the form. – Hans Passant Dec 08 '12 at 16:09
  • @HansPassant my bad, added condition to stop timer. – Sergey Berezovskiy Dec 08 '12 at 16:26
  • It won't work when the user closes the form before the counter reaches 5. You really do have to dispose it. Help him fall in the pit of success by only recommending he drops a Timer component on the form so this is done automatically. – Hans Passant Dec 08 '12 at 16:31
  • Well, we can subscribe to `Closed` event and stop timer there. Or we can create timer with components (but before we should check if components exist for current form). Actually it's better to create components from designer. – Sergey Berezovskiy Dec 08 '12 at 16:38
0

If you invoke Thread.Sleep(500); in your UI thread, the GUI will be unresponsable. That is why you get your Fomr2.label1's background white. I suggest you move your code

while (i < 5)
{
   _form2.label1.Text = "" + i;
   Thread.Sleep(500);
   i++;
}

to another thread. And you can refer to this link to fullfil your goal.

Community
  • 1
  • 1
Colin
  • 551
  • 2
  • 10
  • Most any time you see someone trying to use `Thread.Sleep` in a UI application it means they should be using a `Timer`, not explicitly starting up a background thread just to go do a blocking wait. – Servy Dec 08 '12 at 15:45
  • This is an unresponsable answer. You cannot assign the Text property in a worker thread. – Hans Passant Dec 08 '12 at 16:06
  • @Servy Thank you for reminding me that there is a `Timer` to use in this situation. :) – Colin Dec 08 '12 at 16:10
  • @Hans Passant I have provided a link at the end of the answer which introduces the way to update the UI in another thread. I think it would be help. :) – Colin Dec 08 '12 at 16:12