By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,647 Members | 1,604 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,647 IT Pros & Developers. It's quick & easy.

Form freezing form

P: n/a
Why in this code the form *does not refresh* when it gets the focus/after some time?

#using <mscorlib.dll>
#using <system.windows.forms.dll>
#using <system.dll>
#using <system.drawing.dll>
#include <windows.h>
#include <cstdlib>
// ==> Just a Form with two labels, one progress bar, opacity 90%.
// ==> label1, and progressBar are public and accessed through main().
// ==> Placed some refreshes but the problem persists.
__gc class Form1: public System::Windows::Forms::Form
{
private:
System::Windows::Forms::Label * label2;

public:
System::Windows::Forms::ProgressBar * progressBar1;
System::Windows::Forms::Label * label1;

Form1()
{
this->label2 = new System::Windows::Forms::Label();
this->progressBar1 = new System::Windows::Forms::ProgressBar();
this->label1 = new System::Windows::Forms::Label();

this->label2 = new System::Windows::Forms::Label();
this->progressBar1 = new System::Windows::Forms::ProgressBar();
this->label1 = new System::Windows::Forms::Label();
this->SuspendLayout();

this->label2->Font = new System::Drawing::Font(S"Microsoft Sans Serif", 9.75F,
System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, (System::Byte)161);
this->label2->Location = System::Drawing::Point(14, 16);
this->label2->Name = S"label2";
this->label2->Size = System::Drawing::Size(264, 40);
this->label2->TabIndex = 1;
this->label2->Text = S"Message 1...";
this->label2->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;

this->progressBar1->Location = System::Drawing::Point(10, 176);
this->progressBar1->Name = S"progressBar1";
this->progressBar1->Size = System::Drawing::Size(272, 23);
this->progressBar1->TabIndex = 2;

this->label1->Font = new System::Drawing::Font(S"Microsoft Sans Serif", 8.25F,
System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, (System::Byte)161);
this->label1->Location = System::Drawing::Point(14, 80);
this->label1->Name = S"label1";
this->label1->Size = System::Drawing::Size(264, 64);
this->label1->TabIndex = 3;

this->AutoScaleBaseSize = System::Drawing::Size(5, 13);
this->ClientSize = System::Drawing::Size(292, 271);
this->Controls->Add(this->label1);
this->Controls->Add(this->progressBar1);
this->Controls->Add(this->label2);
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::Fixed3D;

this->Name = S"Form1";
this->Opacity = 0.9;
this->ShowInTaskbar = false;
this->Text = S"Some Application";
this->TopMost = true;
this->ResumeLayout(false);
}
};
int main()try
{
Form1 *pForm1= __gc new Form1;

pForm1->Show();
pForm1->Refresh();

pForm1->label1->Text= "Diagnostic code";
pForm1->progressBar1->Value= 0;
pForm1->progressBar1->Maximum= 100;

while(true)
{
for(long i= 0; i< 100; ++i)
{
pForm1->progressBar1->Increment(1);
pForm1->Refresh();
}

pForm1->progressBar1->Value= 0;
}

}

catch(System::Exception *pe)
{
using namespace System;

Console::WriteLine("Error: {0}", pe->Message);

return EXIT_FAILURE;
}
Nov 17 '05 #1
Share this Question
Share on Google+
13 Replies


P: n/a
Ioannis Vranos wrote:

How about calling Application::DoEvents() instead of pForm1->Refresh()?
DoEvents processes all messages in the message queue and returns. It's
not nearly as good as multithreading, but it's very simple and prevents
your application from freezing while you are processing something that
lasts more than a 100 milliseconds. Call DoEvents periodically, but not
too often, because it slows down your application.

Why in this code the form *does not refresh* when it gets the
focus/after some time?
while(true)
{
for(long i= 0; i< 100; ++i)
{
pForm1->progressBar1->Increment(1);
pForm1->Refresh();
// <<<<<<<<<<<<<<<<<<<<<
Application::DoEvents();
// <<<<<<<<<<<<<<<<<<<<<
}

pForm1->progressBar1->Value= 0;
}

}


Tom
Nov 17 '05 #2

P: n/a
Tamas Demjen wrote:
How about calling Application::DoEvents() instead of pForm1->Refresh()?
DoEvents processes all messages in the message queue and returns. It's
not nearly as good as multithreading, but it's very simple and prevents
your application from freezing while you are processing something that
lasts more than a 100 milliseconds. Call DoEvents periodically, but not
too often, because it slows down your application.


Thanks for the tip Tamas. It appears that it solves the problem, but another one exists.
When I close the Form by pressing the X button, the application process does not
terminate. Any ideas?
Here is the corrected code:
#using <mscorlib.dll>
#using <system.windows.forms.dll>
#using <system.dll>
#using <system.drawing.dll>
#include <windows.h>
#include <cstdlib>
// ==> Just a Form with two labels, one progress bar, opacity 90%.
// ==> label1, and progressBar are public and accessed through main().
// ==> Placed some refreshes but the problem persists.
__gc class Form1: public System::Windows::Forms::Form
{
private:
System::Windows::Forms::Label * label2;

public:
System::Windows::Forms::ProgressBar * progressBar1;
System::Windows::Forms::Label * label1;

Form1()
{
this->label2 = new System::Windows::Forms::Label();
this->progressBar1 = new System::Windows::Forms::ProgressBar();
this->label1 = new System::Windows::Forms::Label();

this->label2 = new System::Windows::Forms::Label();
this->progressBar1 = new System::Windows::Forms::ProgressBar();
this->label1 = new System::Windows::Forms::Label();
this->SuspendLayout();

this->label2->Font = new System::Drawing::Font(S"Microsoft Sans Serif",
9.75F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
(System::Byte)161);
this->label2->Location = System::Drawing::Point(14, 16);
this->label2->Name = S"label2";
this->label2->Size = System::Drawing::Size(264, 40);
this->label2->TabIndex = 1;
this->label2->Text = S"Message 1...";
this->label2->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;

this->progressBar1->Location = System::Drawing::Point(10, 176);
this->progressBar1->Name = S"progressBar1";
this->progressBar1->Size = System::Drawing::Size(272, 23);
this->progressBar1->TabIndex = 2;

this->label1->Font = new System::Drawing::Font(S"Microsoft Sans Serif",
8.25F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
(System::Byte)161);
this->label1->Location = System::Drawing::Point(14, 80);
this->label1->Name = S"label1";
this->label1->Size = System::Drawing::Size(264, 64);
this->label1->TabIndex = 3;

this->AutoScaleBaseSize = System::Drawing::Size(5, 13);
this->ClientSize = System::Drawing::Size(292, 271);
this->Controls->Add(this->label1);
this->Controls->Add(this->progressBar1);
this->Controls->Add(this->label2);
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::Fixed3D;

this->Name = S"Form1";
this->Opacity = 0.9;
this->ShowInTaskbar = false;
this->Text = S"Some Application";
this->TopMost = true;
this->ResumeLayout(false);
}
};
int main()try
{
using namespace System;
using namespace System::Windows::Forms;
using namespace System::Threading;

Form1 *pForm1= __gc new Form1;

pForm1->Show();

pForm1->label1->Text= "Diagnostic code";
pForm1->progressBar1->Value= 0;
pForm1->progressBar1->Maximum= 100;

while(true)
{
for(long i= 0; i< 100; ++i)
{
pForm1->progressBar1->Increment(1);

if(i%10== 0)
Application::DoEvents();

Thread::Sleep(100);
}

pForm1->progressBar1->Value= 0;
}

}

catch(System::Exception *pe)
{
using namespace System;

Console::WriteLine("Error: {0}", pe->Message);

return EXIT_FAILURE;
}
Nov 17 '05 #3

P: n/a
Ioannis Vranos wrote:
Thanks for the tip Tamas. It appears that it solves the problem, but
another one exists. When I close the Form by pressing the X button, the
application process does not terminate. Any ideas?


If I'm not mistaken, your main function if in a forever loop. This is
not typical in real-world applications. Usually your processing finishes
sooner or later. If you want to be able to cancel a long lasting
operation, you could have a Cancel button, which would set an
IsCancelled flag on click. Your main loop could then check against this
flag. This is how typical applications work.

I almost always perfer using threads, as opposed to DoEvents, because
threads have automatic load balancing, and you don't have to figure out
how often DoEvents should be called. It's also dangerous to call
DoEvents, because it may call other functions you are not prepared for
(it can have serious side effects, unwanted recursion, etc.).

When using DoEvents, your application won't be as smooth and responsive
as using threads. You either call DoEvents too often, which slows down
your processing, or you call it too rarely, which makes the GUI sluggish
during processing. There is no such problem with threads, as the system
scheduler is very smart, and you can even assign priorities to threads.
Assigning low priority you can instruct the system to "do it if you have
time, otherwise don't".

Tom
Nov 17 '05 #4

P: n/a
You never give a chance to your application to handle the paint message
posted to the application queue, your infinite loop takes all processing
time.
One bad advise would be to call DoEvents, but he! we are slowly moving to 64
bit OS'ses and this is a something that's been used on 16 bit non-preemptive
windows.
You should run your task (not really a realistic one) on another thread and
update the UI from there using Control::Invoke or BeginInvoke.

Willy.
Willy.

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:%2***************@TK2MSFTNGP12.phx.gbl...
Why in this code the form *does not refresh* when it gets the focus/after
some time?

#using <mscorlib.dll>
#using <system.windows.forms.dll>
#using <system.dll>
#using <system.drawing.dll>
#include <windows.h>
#include <cstdlib>
// ==> Just a Form with two labels, one progress bar, opacity 90%.
// ==> label1, and progressBar are public and accessed through main().
// ==> Placed some refreshes but the problem persists.
__gc class Form1: public System::Windows::Forms::Form
{
private:
System::Windows::Forms::Label * label2;

public:
System::Windows::Forms::ProgressBar * progressBar1;
System::Windows::Forms::Label * label1;

Form1()
{
this->label2 = new System::Windows::Forms::Label();
this->progressBar1 = new System::Windows::Forms::ProgressBar();
this->label1 = new System::Windows::Forms::Label();

this->label2 = new System::Windows::Forms::Label();
this->progressBar1 = new System::Windows::Forms::ProgressBar();
this->label1 = new System::Windows::Forms::Label();
this->SuspendLayout();

this->label2->Font = new System::Drawing::Font(S"Microsoft Sans Serif",
9.75F, System::Drawing::FontStyle::Regular,
System::Drawing::GraphicsUnit::Point, (System::Byte)161);
this->label2->Location = System::Drawing::Point(14, 16);
this->label2->Name = S"label2";
this->label2->Size = System::Drawing::Size(264, 40);
this->label2->TabIndex = 1;
this->label2->Text = S"Message 1...";
this->label2->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;

this->progressBar1->Location = System::Drawing::Point(10, 176);
this->progressBar1->Name = S"progressBar1";
this->progressBar1->Size = System::Drawing::Size(272, 23);
this->progressBar1->TabIndex = 2;

this->label1->Font = new System::Drawing::Font(S"Microsoft Sans Serif",
8.25F, System::Drawing::FontStyle::Regular,
System::Drawing::GraphicsUnit::Point, (System::Byte)161);
this->label1->Location = System::Drawing::Point(14, 80);
this->label1->Name = S"label1";
this->label1->Size = System::Drawing::Size(264, 64);
this->label1->TabIndex = 3;

this->AutoScaleBaseSize = System::Drawing::Size(5, 13);
this->ClientSize = System::Drawing::Size(292, 271);
this->Controls->Add(this->label1);
this->Controls->Add(this->progressBar1);
this->Controls->Add(this->label2);
this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::Fixed3D;

this->Name = S"Form1";
this->Opacity = 0.9;
this->ShowInTaskbar = false;
this->Text = S"Some Application";
this->TopMost = true;
this->ResumeLayout(false);
}
};
int main()try
{
Form1 *pForm1= __gc new Form1;

pForm1->Show();
pForm1->Refresh();

pForm1->label1->Text= "Diagnostic code";
pForm1->progressBar1->Value= 0;
pForm1->progressBar1->Maximum= 100;

while(true)
{
for(long i= 0; i< 100; ++i)
{
pForm1->progressBar1->Increment(1);
pForm1->Refresh();
}

pForm1->progressBar1->Value= 0;
}

}

catch(System::Exception *pe)
{
using namespace System;

Console::WriteLine("Error: {0}", pe->Message);

return EXIT_FAILURE;
}

Nov 17 '05 #5

P: n/a
Willy Denoyette [MVP] wrote:
You never give a chance to your application to handle the paint message
posted to the application queue, your infinite loop takes all processing
time.
One bad advise would be to call DoEvents, but he! we are slowly moving to 64
bit OS'ses and this is a something that's been used on 16 bit non-preemptive
windows.
You should run your task (not really a realistic one) on another thread and
update the UI from there using Control::Invoke or BeginInvoke.

This is about a window displaying progress of file operations. I assume a form is the only
thing that can be used as a "window". I want to display each file operation. Is your
suggestion that I can't do much else than skipping to display all file operations, but
instead display only from here and there?

The behaviour I am experiencing is exactly the same with this sample application, the form
freezes, but the program itself (a method of the form calling a couple of other methods of
the form) continues normally.
Nov 17 '05 #6

P: n/a
Ioannis Vranos wrote:
This is about a window displaying progress of file operations. I assume
a form is the only thing that can be used as a "window". I want to
display each file operation. Is your suggestion that I can't do much
else than skipping to display all file operations, but instead display
only from here and there?

The behaviour I am experiencing is exactly the same with this sample
application, the form freezes, but the program itself (a method of the
form calling a couple of other methods of the form) continues normally.

It seems that the problem got fixed after placing an Application::DoEvents() call at each
iteration.

However if you have some more elegant idea, I would be glad to hear it (executing the file
processing method in a separate thread and letting it modify the Form from there does not
work, the program freezes).
Nov 17 '05 #7

P: n/a
Ioannis Vranos wrote:
It seems that the problem got fixed after placing an
Application::DoEvents() call at each iteration.

However if you have some more elegant idea, I would be glad to hear it
(executing the file processing method in a separate thread and letting
it modify the Form from there does not work, the program freezes).

you= you both, or someone else.
Nov 17 '05 #8

P: n/a
Ioannis Vranos wrote:
However if you have some more elegant idea, I would be glad to hear it
(executing the file processing method in a separate thread and letting
it modify the Form from there does not work, the program freezes).


Using a separate threads is the only reasonable and elegant solution.
It's not terribly hard to do, but you really have to be careful. Writing
thread safe code is hard, and if you miss something, it will freeze or
crash.

I haven't tried threads in .NET/WinForms, but use them all the time in
unmanaged applications, when a progress dialog is needed for a
long-lasting operation.

When you update the form from the thread, are you taking care of the
synchronization? Only the main thread is allowed to modify the GUI, you
can't do it directly from the thread, you have to do the update via
Control::Invoke.

There are tutorials out there, although few of them are C++, you can
still get the point from them:
http://samples.gotdotnet.com/quickst...olinvoker.aspx
http://samples.gotdotnet.com/quickst...rshalling.aspx
http://www.dotnetspider.com/technology/kbpages/903.aspx

Tom
Nov 17 '05 #9

P: n/a
Tamas Demjen wrote:
When you update the form from the thread, are you taking care of the
synchronization? Only the main thread is allowed to modify the GUI, you
can't do it directly from the thread, you have to do the update via
Control::Invoke.

Do you mean I should create a delegate for this? However my question is this, as far as I
understand, before the Application::DoEvents() use, the form got "frozen" because of the
frequency of the updates. Why this will not happen when Invoke() is used?
Nov 17 '05 #10

P: n/a

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:Oo**************@tk2msftngp13.phx.gbl...
Tamas Demjen wrote:
When you update the form from the thread, are you taking care of the
synchronization? Only the main thread is allowed to modify the GUI, you
can't do it directly from the thread, you have to do the update via
Control::Invoke.

Do you mean I should create a delegate for this? However my question is
this, as far as I understand, before the Application::DoEvents() use, the
form got "frozen" because of the frequency of the updates. Why this will
not happen when Invoke() is used?


Because your actual work is done on another thread and as such doesn't block
the thread's message pump, the only thing what's done on the UI thread is
updating the UI (paint, handle mouse moves/clicks, KB input etc...).
Note that Control.Invoke and (preferable) BeginInvoke simply post a message
(that basically contains the address of the function to execute) to the
message queue, such that the function is executed on the UI thread (well the
thread owning the Control).

Willy.
Nov 17 '05 #11

P: n/a
Willy Denoyette [MVP] wrote:
Because your actual work is done on another thread and as such doesn't block
the thread's message pump, the only thing what's done on the UI thread is
updating the UI (paint, handle mouse moves/clicks, KB input etc...).
Note that Control.Invoke and (preferable) BeginInvoke simply post a message
(that basically contains the address of the function to execute) to the
message queue, such that the function is executed on the UI thread (well the
thread owning the Control).

Apologies for bothering you with this, I am just considering if my code conversion to
multithreading will offer any advantage over the Application::DoEvents().

The story is this, there is a file processing member function that executes as fast as
possible, and the aim is the form displaying every file processed. That is, even in the
case of BeginInvoke(), the form will be flooded with control changes (progress bar and
label text), so I suppose two things will happen if I separate this in two threads. Either
the form will not display all files but as much files as it will manage (= with delay?),
or it will appear frozen again and thus Application::DoEvents() will be used to. I suppose
in multicore CPUs the application will probably manage to draw everything in the case of
two threads, however I am interested this to happen in single-core CPUs too.
So my question is this, since Application:DoEvents() does the job acceptably, should I
stick to this or is it certain that placing the form in a separate thread of the file
processing and "flooding" it with the same rate as before will have a different behaviour
than before, and thus will make the use of Application::DoEvents() unnecessary?
Thank you all for the information that you have provided me so far.
Nov 17 '05 #12

P: n/a

"Ioannis Vranos" <iv*@remove.this.grad.com> wrote in message
news:OR*************@TK2MSFTNGP12.phx.gbl...

So my question is this, since Application:DoEvents() does the job
acceptably, should I stick to this or is it certain that placing the form
in a separate thread of the file processing and "flooding" it with the
same rate as before will have a different behaviour than before, and thus
will make the use of Application::DoEvents() unnecessary?
Thank you all for the information that you have provided me so far.


In my opinion you should forget about DoEvents and prefer background worker
threads for non UI related processing.
DoEvents is a hack invented for languages that don't support multithreading,
running such applications will not take advantage of multicore CPU's at
all.....

Now your question about "flooding the UI", all depends on how frequently you
need/want to update the UI. I suppose you want to keep the impact of the
file processing time by this UI update as small as possible, and you don't
need to update the UI so frequently that the user can't visually see the
difference between successive updates.
Consider following small sample:
The DoWork function runs on a background thread and reads a file
(mscorlib.xml - 4790 KB) in chunks of 256 bytes, asynchronously updating the
UI every 4096 bytes read. On a entry level box, this will take less than a
couple of seconds when the file is not in the cache, and less than a second
if the file is cached.
During that time the UI will be updated 1196 times which is
1. way to fast for a good user experience.
2. UI thread and thread switching takes to much processing power
So what you have to do is find an acceptable interval to update the UI,
without
Note that I'm not exactly processing the file data, so I need to give up my
thread quantum each time I want to update the UI, in a real world scenario
this may not be necessary as the scheduler will preempt to worker thread at
regular intervals to let the UI thread process it's message queue.
Compile and run the program, and play a bit with the frequency of updates to
see exactly what I mean.

Willy.

#using <system.windows.forms.dll>
#using <system.dll>
#using <system.drawing.dll>
using namespace System;
using namespace System::IO;
using namespace System::Text;
using namespace System::Windows::Forms;
using namespace System::Drawing;
using namespace System::Threading;
namespace Win
{
__delegate void StringParameterDelegate(String * s);

public __gc class Form1 : public Form
{
// Methods
public:
Form1()
{ InitializeComponent();}
protected:
virtual void Dispose(Boolean disposing)
{
__super::Dispose(disposing);
}
private: Button* button1;
Label * cntText;
System::ComponentModel::Container __gc * components;
void InitializeComponent(void)
{
this->button1 = (new Button());
this->cntText = new Label();
this->SuspendLayout();
this->button1->Location = System::Drawing::Point(65, 25);
this->button1->Size = System::Drawing::Size(60, 25);
this->button1->TabIndex = 0;
this->button1->Text = L"button1";
this->button1->Click += new System::EventHandler(this,
&Form1::button1_Click);
this->cntText->Location = System::Drawing::Point(5, 5);
this->cntText->Size = System::Drawing::Size(185, 15);
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(200, 62);
this->Controls->Add(this->button1);
this->Controls->Add(this->cntText);
this->Text = L"MThreaded Form";
this->ResumeLayout(false);
}
private: void button1_Click(System::Object* sender, System::EventArgs*
e)
{
ThreadStart* myThreadDelegate = new ThreadStart(this,
&Win::Form1::DoWork);
Thread* t = new Thread(myThreadDelegate);
t->IsBackground = true;
t->Start();
}
void DoWork()
{
FileStream* fs =
File::OpenRead("C:\\WINDOWS\\Microsoft.NET\\Framew ork\\v1.1.4322\\mscorlib.xml");
String* status;
int bytesRead = 0;
int offset = 0;
int count = 0;
try {
Byte b[] = new Byte[256];
UTF8Encoding* temp = new UTF8Encoding(true);
while ((bytesRead = fs->Read(b, 0, b->Length)) > 0) {
offset += bytesRead;
if(offset % 4096 == 0)
{
status = String::Format(S"UI Thread accessed {0} times.",
__box(count++));
UpdateUIStatus(status);
Threading::Thread::Sleep(0); // Give other threads a chance to run by
giving up our thread quantum
}
}
}
__finally
{
if (fs) __try_cast<IDisposable*>(fs)->Dispose();
}
}
void UpdateUIStatus(String *value)
{
// Are we running on the UI thread?
if (InvokeRequired)
{
StringParameterDelegate *spd = new StringParameterDelegate(this,
&Win::Form1::UpdateUIStatus);
String *obj __gc[] = { value};
// We're not in the UI thread, so we need to call BeginInvoke
BeginInvoke(spd, obj);
return;
}
// Must be on the UI thread if we've got this far
// Here we can safely touch the UI, or do anything the UI can do
cntText->ForeColor = Color::Red;
cntText->Text = value;
}
};
}
using namespace Win;
[STAThreadAttribute]
int main()
{
Application::Run(new Form1());
return 0;
}

Nov 17 '05 #13

P: n/a
Willy Denoyette [MVP] wrote:
In my opinion you should forget about DoEvents and prefer background worker
threads for non UI related processing.
DoEvents is a hack invented for languages that don't support multithreading,
running such applications will not take advantage of multicore CPU's at
all.....

Now your question about "flooding the UI", all depends on how frequently you
need/want to update the UI. I suppose you want to keep the impact of the
file processing time by this UI update as small as possible, and you don't
need to update the UI so frequently that the user can't visually see the
difference between successive updates.
Consider following small sample:
The DoWork function runs on a background thread and reads a file
(mscorlib.xml - 4790 KB) in chunks of 256 bytes, asynchronously updating the
UI every 4096 bytes read. On a entry level box, this will take less than a
couple of seconds when the file is not in the cache, and less than a second
if the file is cached.
During that time the UI will be updated 1196 times which is
1. way to fast for a good user experience.
2. UI thread and thread switching takes to much processing power
So what you have to do is find an acceptable interval to update the UI,
without
Note that I'm not exactly processing the file data, so I need to give up my
thread quantum each time I want to update the UI, in a real world scenario
this may not be necessary as the scheduler will preempt to worker thread at
regular intervals to let the UI thread process it's message queue.
Compile and run the program, and play a bit with the frequency of updates to
see exactly what I mean.

OK, thank you a lot for the information.
Nov 17 '05 #14

This discussion thread is closed

Replies have been disabled for this discussion.