Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm having trouble working out the correct architecture for the following task. I have a GUI in Windows Forms that contains a ListBox, listing certain architectural layouts. One an item in this list is selected, a custom Control displays an interactive visualization of the selected layout. Drawing of this interactive diagram is a CPU-intensive task, and can take up to a second on my machine.

The kind of functionality I'm trying to achieve is that if a user wants to quickly scroll through the layouts in the ListBox (say, holding down the down arrow key), I don't want my computer to sit there thinking about how to draw the layout before it allows the user to do anything else.

The obvious answer is, of course, to run the layout calculations in a separate thread. But how do I make that thread return a whole control? How do I make sure I'm not running two layout calculations at once?

I'm fairly new to this complex GUI business. So the real question is what is the right architecture to implement something like this? This seems like something people do all the time, but finding any suggestions on how to do it properly is really difficult.

share|improve this question

migrated from stackoverflow.com Apr 30 '11 at 6:12

This question came from our site for professional and enthusiast programmers.

3 Answers 3

up vote 2 down vote accepted

Like Steve Townsend said, the key here is the BackgroundWorker.

Since your background worker is the one that draws something on the screen you need to hide the control that is being drawn from view as long as it is not finished. To do that I would draw the content to a hidden control built dynmically and display it only when:

  • the background worker has finished
  • (optionally) the selected entry in the listbox is related to the worker that has finished (to manage concurrency)

So when a entry is selected in the listbox:

  • Create a worker related to the entry, the worker should perform his work on a hidden control.
  • Add methods for listening to DoWork and RunWorkerCompleted. The first one for starting your drawing, the second one for when the drawing is over.
  • Attempt to cancel other workers that have not yet finished by calling the CancelAsync on them
  • Launch the worker by calling RunWorkerAsync()
  • OnRunWorkerCompleted --> Hide the previously displayed control, show the new control the worker has been drawing on.

Additionally, if your listbox is not a drop down listbox, you should add a delay(for example 0.2s) to the method listening for changes in the listbox in order to avoid launching workers too fast and when not needed.

Hope that helps!

share|improve this answer

If I understand it correctly, your use case is just like a folder with many files and a preview panel, and you want that if the user scrolls through the list, they can do it smoothly, without waiting for the preview to be fully displayed before moving the cursor to the next file.

I don't see a lot of architecture involved here. You have to write a handler for cursor movements and at each key press stop the rendering of the previous file, if any, and start the rendering of the current file.

share|improve this answer

Take a look at using BackgroundWorker for your long-running task. Making sure you only do it once requires some kind of inter-thread synchronization - a flag with a lock() on it, say.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.