?
Solved

Trouble Updating Controls From Within a While Loop

Posted on 2004-08-12
3
Medium Priority
?
159 Views
Last Modified: 2010-04-15
I've written a function that is supposed to update a listbox and a label every time I iterate through a while loop. For some reason, the controls are not being updated. However, when I terminate the loop prematurely (with a return statement) both controls update correctly.

Is this typical behavior for a while loop, or is there something odd going on with the controls?
0
Comment
Question by:nh_capricorn
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 2

Expert Comment

by:davidastle
ID: 11790277
To make a long story short, it has to with windows.  To force your controls to be shown as they truly are, call the Update() function on your window or on a control.

The weird behavior has to do with the way windows works.

Your application knows when to redraw itself because windows will send it a message called WM_PAINT.  The caveat is that windows will only send this message if your messages queue is empty, and when you are constantly changing controls in a while loop, your message queue is never empty.

It does not have to with while loops.   Lets say that you have an infinite loop that starts when you click on your window and updates your textbox.  To test to see if its doing anything, lets make it do something more than just update the text data.
Make sure your project properties are set so to console application to follow my code.

while (true)
{
    myTextBox.Text += "Foo";
    Console.WriteLine(myTextBox.Text);
}

If you run this, you will see that your text box data is in fact getting updated.  The reason why it is not displaying is because of windows!  Microsoft is not sending you WM_PAINT messages.  To prove this, lets track all the windows messages that are sent your app.  Make a new windows form project, and set it to console application.  Now, create a new class below your form class called MyFilter and make it inherit IMessageFilter.  This will be used to track the windows messages that are passed to your window.  Next, you have to add the filter when the application loads.  Here is an example that will start your loop when you click the mouse button.  It will show all the windows messages past in a console window:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace WindowsApplication1
{
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
      {
            private System.Windows.Forms.TextBox textBox1;
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;

            public Form1()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();

                  //
                  // TODO: Add any constructor code after InitializeComponent call
                  //
                  this.Load +=new EventHandler(Form1_Load);
                  this.MouseDown +=new MouseEventHandler(Form1_MouseDown);
            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  this.textBox1 = new System.Windows.Forms.TextBox();
                  this.SuspendLayout();
                  //
                  // textBox1
                  //
                  this.textBox1.Location = new System.Drawing.Point(88, 112);
                  this.textBox1.Name = "textBox1";
                  this.textBox1.Size = new System.Drawing.Size(376, 20);
                  this.textBox1.TabIndex = 0;
                  this.textBox1.Text = "textBox1";
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(600, 478);
                  this.Controls.Add(this.textBox1);
                  this.Name = "Form1";
                  this.Text = "Form1";
                  this.ResumeLayout(false);

            }
            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
      
            static void Main()
            {
                  Application.Run(new Form1());
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                  Application.AddMessageFilter(new MyFilter());
            }

            private void Form1_MouseDown(object sender, MouseEventArgs e)
            {
                  while (true)
                  {
                        this.textBox1.Text += "A";
                        Console.WriteLine(this.textBox1.Text);
                  }
            }
      }
      public class MyFilter : IMessageFilter
      {
            #region IMessageFilter Members

            public bool PreFilterMessage(ref Message m)
            {
                  // TODO:  Add MyFilter.PreFilterMessage implementation
                  Console.WriteLine(m.Msg);
                  return false;
            }

            #endregion

      }

}

As you will see, windows stops sending messages once your loop starts, including the WM_PAINT message.  The reason why windows will not send the message is because your application message queue is never empty, and windows is waiting for it to be empty.  For more info on WM_PAINT, go to http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_88ac.asp

If you call the Update() function on your control or form, it will force the window to be repainted.
0
 
LVL 2

Accepted Solution

by:
davidastle earned 1200 total points
ID: 11790295
So instead of:
while (true)
{
   myTextBox.Text += "A";
}
Do:
while (true)
{
   myTextBox.Text += "A";
   myTextBox.Update();
}
You could also call the Update function on the current window (this.Update()).  This will automatically update every child control as well.
0
 

Author Comment

by:nh_capricorn
ID: 11800858
Thanks David!

I really appreciate all of the detail you put into your answer. Guess I'm just going to have to get used to programming with windows (Java was a lot simpler, IMO).

- nhc
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
Michael from AdRem Software outlines event notifications and Automatic Corrective Actions in network monitoring. Automatic Corrective Actions are scripts, which can automatically run upon discovery of a certain undesirable condition in your network.…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…
Suggested Courses

752 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question