views:

281

answers:

4

My program consists of a large graphing UI control that I need to spend about 15 seconds re-loading every once in a while. Because the updating code works primarily with the UI control (maybe 90% of it actually sets properties on the control), it would make sense to me to actually let the UI thread handle that. I really don't want the control to visually re-paint while it is loading in a separate thread from the UI.

I also want a progress bar to update as well that lives in the status bar of the same application window. Is there a way to break the rule in this case and re-paint only the progress bar, or should I just open a new application window for the progress bar to live in?

What would you do in this particular case?

A: 

Find a graphing UI control that is more efficient. Unless the UI thread yields to the message loop any other updates won't happen (and it will slow down your graph control's updates).

Richard
Most times the update is only about 2 to 5 seconds, but could be up to 20 seconds in the extreme. Would you just live with it and forget about the progress bar? Unfortunately finding a better graphing control is not possible right now.
Ben McIntosh
A: 

I would suggest using a progressbar in a new window (without the form headers). Make it paint the progress bar by reading the shared properties of a graph control. this way you can avoid the thread blocking (sluggish loading).. And it gives you good visual experience (progressive painting on both the controls).

Cheers

Ramesh Vel

Ramesh Vel
+1  A: 

It is not really true that there is only one UI thread in an application, it is just that most windows applications only ever create UI objects in one thread so this thread becomes "the" UI thread in the application. It is easy to understand why - this makes the code simpler to understand, and protects us from implicit thread binding issues between controls.

This suggests a possible idea, should it prove impossible to improve the speed of updating the control (which is what I would suggest to do first). Create the UI control on a separate thread. You need to make sure that the thread is suitable for UI, that is to say the threading model is STA, and that it will pump messages and not die before the control is destroyed. I don't know if you need to create the parent window in the UI thread as well, or just the control but it may be worth experimenting here.

1800 INFORMATION
You can't create a control on thread A and then parent it to a control you created on thread B. If you try, you'll get an InvalidOperationException: "The calling thread cannot access this object because a different thread owns it." Everything inside a window has to be on the same thread. That said, you could make this work if the progress bar thread had its own window.
Joe White
+2  A: 

If you can break your primary task (ie. updating the graph) in many steps, you can perform each step as a separate dispatcher message. This will allow other messages to be processed, including giving you the ability to update progress information.

The basic pattern is:

  1. Invoke your primary task, passing in zero for the step.
  2. Perform the step.
  3. If there are more steps, queue another message, passing in step + 1.

You can then add in progress updates at the appropriate points in your code.

HTH, Kent

PS. Not saying this is your best option - hard to tell without knowing all the details. But this is an option.

Kent Boogaart