Using a Progress Dialog with Multi-Threading

multithreadingpatterns-and-practices

My .NET Windows desktop application creates an HTML report, and has 3 main phases. It may create multiple reports.

I show a progress bar so the user knows (estimates) how long it will take (as well as reassure the system didn't crash by an updating GUI). So, if I needed to generate 3 reports, there would be a total of 9 phases (3 phases * 3 reports).

The issue I now have, is the process is taking too long. As such, I need to use threads so I can start on phase 1, then open a new thread which completes phase 2 and 3. Whilst phase 2 and 3 are in progress, the next item on the list begins with phase 1 and the process continues. I'm hoping this makes sense.

So I'm now thinking what to do with the progress bar since multiple phases will be being run at once. At the moment, the only logical thing I can think of is

Report 1. Start phase 1. New thread -> Phase 2 and 3

Check to see if Report 2 is last report. It isn't, so, during Report 2 phase 2, start Report 2 phase 1. New thread -> Phase 2 and 3

Check to see if Report 3 is last report. It is. So, during report 2 phase 2, start Report 3 phase 1, then continue on the same thread with phase 2 and 3

The above will mean I update the Progress Dialog during phase 2 and 3 of the last Report (and I guess I need to add some checks to ensure the other phases are actually finished).

I can't imagine I'm doing any thing new or different to what has been before and as such, I was wondering if there is already a pattern for dealing with type of situation?

Best Answer

I would try to organize it into tasks, which is to say a job that is one-to-one with your phases. In other words if you have 3 reports with 3 phases each, you will have 3*3 or 9 tasks.

It would seem that some of these tasks can be run in parallel while others can't, so I would allow a task object to wrap another task, with the intended meaning that once the outer task is finished, it will simply call the inner task in the same thread.

Once you've done this, there really should be only 6 such tasks (3 of which execute phase 2 and wrap task for phase 3). At this point you can safely execute all 6 tasks using a thread pool of some sort with a minimum and maximum thread count.

At this point, in order to update the progress bar, I would add a recursive method to task object which asks how many tasks are to be performed, and it would be 1 + recursive call to inner task. Given a list of tasks, you should be able to use this method to determine the amount of progress steps.

From there, when you launch each task, you should optionally pass a progress bar control which updates it once the task is finished and then passes the same instance to inner tasks if there are any.

Since it is using threading, the progress bar may update a little sporadically, but such is the nature of threads. I hope that points you to the right direction.