How to get controls to update during heavy activity

R

rob

I've got a couple stretches of code where I use a lot of CPU on
various operations. Since this is happening in a loop at unrestriicted
speed, some of the form controls do not update. (Actually surprising
that some do and some don't).

Also some buttons become unresponsive.

What's the recommended way of giving time back to the UI so it can
service and update the controls and respond to button clicks?

(Hard to think of good Google search keys for this one)
 
M

Marc Gravell

Simple - don't do that work on the UI thread, but instead fire up a
worker thread - perhaps using BackgroundWorker or ThreadPool. The UI
thread simply starts the work going, then goes back to processing
messages. The only complexity is that the worker thread *cannot* talk
directly to the Controls (thread affinity; both read & write), so must
instead ask the UI thread for a little help, via Control.Invoke (sync)
and Control.BeginInvoke (async)

i.e.

void StartWorkHandler(object sender, EventArgs args) {
// runs on the UI thread
ThreadPool.QueueUserWorkItem(WorkMethod);
}
void WorkMethod(object state) {
// runs on the worker thread
for (int i = 0; i < 1000; i++) {
// simulate some heavy work in a loop
Thread.Sleep(500);

// update UI on every 10th cycle
if ((i % 10) == 0) {
// *important* if using async, don't access the
vars (i)
// from both threads at once; in this case, we'll
make
// a string on the worker thread that is then
never
// changed, so we can rely on it on the UI thread;
// can also just use sync (Invoke) to make this
easier,
// but done incorrectly this can show deadlocks...
string newFormText = "Cycle " + i.ToString();
BeginInvoke((MethodInvoker)delegate {
// runs (async) on the UI thread
Text = newFormText;
});
}
}
}

Marc
 
R

Rob

Simple - don't do that work on the UI thread, but instead fire up a
worker thread - perhaps using BackgroundWorker or ThreadPool. The UI
thread simply starts the work going, then goes back to processing
messages. The only complexity is that the worker thread *cannot* talk
directly to the Controls (thread affinity; both read & write), so must
instead ask the UI thread for a little help, via Control.Invoke (sync)
and Control.BeginInvoke (async)

Thanks, Marc. I was afraid you were going to say that. <g>

This particular stretch of code may take a lot of work to run it on
another thread. In other programs I've used Invoke for access to UI
threads, but this one won't go quietly.

In this case I'm triggering the CPU-hog process via a button. It
updates values that are polled by a dispatch loop on a
System.Forms.Timer (which runs in the UI thread). Some UI controls
DO update. Text in TextBoxes does not. Also Button events don't
propagate back.

Given that some of the controls do work, I was hoping that there was a
way to delegate enough CPU to get the others working too.
No other solution except another thread, eh?
 
P

Peter Duniho

[...]
In this case I'm triggering the CPU-hog process via a button. It
updates values that are polled by a dispatch loop on a
System.Forms.Timer (which runs in the UI thread). Some UI controls
DO update. Text in TextBoxes does not.

Are you saying that you have multiple values being polled, some of which
are reflected in the form and some of which are not? That sounds like you
have a bug in either your value-polling code or the UI-updating code.
Also Button events don't propagate back.

Propagate back from where to where? Why should button events (Click, I
assume you mean?) have to propagate at all? Should they not be handled in
the same thread that is already correctly polling values and updating the
UI?
Given that some of the controls do work, I was hoping that there was a
way to delegate enough CPU to get the others working too.
No other solution except another thread, eh?

If your code isn't running, it's not because the thread is being starved.
Unless you are doing something evil like changing thread priority, it's
not possible for one thread in your process to completely prevent other
threads from getting CPU time.

You have a bug. Maybe more than one.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top