<p style="margin: 0.0px 0.0px 12.0px 0.0px; font: 12.0px Helvetica">I recently got to investigate issues in p2 why the progress bar did not move while it was very clear that things where happening as subtasks changed the text. Looking into what was going on made me find a new Progress Monitor anti pattern.</p>

+

<p style="margin: 0.0px 0.0px 12.0px 0.0px; font: 12.0px Helvetica">The problem is how to handle a case where you need to do something like this:</p>

<p style="margin: 0.0px 0.0px 15.0px 0.0px; font: 14.0px Helvetica"><span style="font-size: 12px;">Well, what is wrong with this, you may ask… Well, the length of the progress bar will be divided into as many slots as there are candidates, and if the first candidate succeeds and uses its 1000 ticks, and the remaining candidates are never considered, we will end up reporting the 1000 ticks on a fraction of the overall progress bar. This means that for 10 candidates, you will see the progress-bar slowly go to about 10% of the overall length, to suddenly jump to 100%.</span></p>

+

<br/>

+

<p style="font: 14.0px Helvetica"><b>Good pattern</b></p>

+

<p style="margin: 0.0px 0.0px 12.0px 0.0px; font: 12.0px Helvetica">Here is the good pattern that makes use of the full progress bar:</p>

<p style="font: 12.0px Helvetica">Notice how “setWorkRemaining” is called each time in the loop. This reallocates the remaining ticks, but there is no need to compute how many that actually remains, the child allocation of 1000 ticks will always give the child 1000 ticks to report, even if there were not enough ticks left in the parent. All the scaling is performed by the SubMonitor, so you don’t have to worry about it.</p>

+

<p style="font: 12.0px Helvetica; min-height: 14.0px">Now, let’s say that the routine you are calling do need to perform a bit of work even if it does not need all of its ticks. Don’t worry, that will work too as long as it is a small portion of the allocation. If you risk consuming a larger part, you may be better off doing a true partitioning of the progress-bar as shown in the next section.</p>

<p style="font: 12.0px Helvetica">Here I simply use SubMonitor’s <span style="font: 12.0px Monaco">newChild,</span> this works without calling “done” because the next call to newChild (or “done” for that matter) will consume the ticks allocated for the child.</p>

+

<br/>

+

<p style="font: 14.0px Helvetica"><b>Rules of Thumb</b></p>

+

<ol style="list-style-type: decimal">

+

<li style="font: 12.0px Helvetica">Use SubMonitor</li>

+

+

<li style="font: 12.0px Helvetica">Always begin by converting the monitor you get to a SubMonitor</li>

+

+

<li style="font: 12.0px Helvetica">Use newChild(n) to create a sub monitor to pass to methods that take an IProgressMonitor as argument.</li>

+

+

<li style="font: 12.0px Helvetica">Never call “done” - but document that the caller must do so unless they used a SubMonitor</li>

+

</ol><br />

[[Category:Best_Practices]]

[[Category:Best_Practices]]

Revision as of 17:01, 11 May 2009

I recently got to investigate issues in p2 why the progress bar did not move while it was very clear that things where happening as subtasks changed the text. Looking into what was going on made me find a new Progress Monitor anti pattern.

The problem is how to handle a case where you need to do something like this:

for(inti =0; i < candidates.length; i++)

if(loadCandidate1(i))

break;

Where a call to loadCandidate is potentially a long running task. The first loaded candidate means we are done.

Antipattern

Here is an implementation of the above example using the antipattern - i.e. "don't do this":

Well, what is wrong with this, you may ask… Well, the length of the progress bar will be divided into as many slots as there are candidates, and if the first candidate succeeds and uses its 1000 ticks, and the remaining candidates are never considered, we will end up reporting the 1000 ticks on a fraction of the overall progress bar. This means that for 10 candidates, you will see the progress-bar slowly go to about 10% of the overall length, to suddenly jump to 100%.

Notice how “setWorkRemaining” is called each time in the loop. This reallocates the remaining ticks, but there is no need to compute how many that actually remains, the child allocation of 1000 ticks will always give the child 1000 ticks to report, even if there were not enough ticks left in the parent. All the scaling is performed by the SubMonitor, so you don’t have to worry about it.

Now, let’s say that the routine you are calling do need to perform a bit of work even if it does not need all of its ticks. Don’t worry, that will work too as long as it is a small portion of the allocation. If you risk consuming a larger part, you may be better off doing a true partitioning of the progress-bar as shown in the next section.

Good pattern - regular loop

Here is the good pattern for a regular loop where each iteration does consume ticks