Solved

Trouble Updating Controls From Within a While Loop

Posted on 2004-08-12
3
151 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
  • 2
3 Comments
 
LVL 2

Expert Comment

by:davidastle
Comment Utility
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 300 total points
Comment Utility
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
Comment Utility
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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
What are the big features of MVC5? 4 50
WPF issue with Trigger 2 65
Async and await with MVC and Web Api 3 29
LINQ question 7 20
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…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

771 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now