Displaying Progress using LINQPad’s Util.ProgressBar

LINQPad contains a number of very useful utilities, as documented here. One of these is the Util.ProgressBar functionality which allows you to display the progress of your script within the results pane. This can be very useful when, say, you are updating a large number of records and want an indication of progress without having to write additional information out to the results pane for every record or group of records. Whilst the use of the ProgressBar is very straightforward, I was caught out by a very simple detail when I first started using it, so thought it worth documenting in detail here.

Here’s the most straightforward example of the ProgressBar:

var pb = new Util.ProgressBar("Analyzing data");
pb.Dump();
for (int index = 0; index <= 100; index++)
{
    pb.Percent = index;
    Thread.Sleep(100);
}

This will result in a progress bar being displayed in the results pane like this:

The general procedure for using the progress bar is as follows.

Instantiate the progress bar, with its optional title:

var pb = new Util.ProgressBar("Analyzing data");

Dump the progress bar to the results pane so it is visible:

pb.Dump();

Update the progress bar, using either its ‘Percent’ property (an integer) or its ‘Fraction’ property (a double).

var pb = new Util.ProgressBar("Progress");
pb.Dump();
float total = 90;
float complete = 32;
pb.Percent = (int)((complete/total)*100);

or

var pb = new Util.ProgressBar("Progress");
pb.Dump();
float total = 90;
float complete = 32;
pb.Fraction = complete/total;

Optionally, you can also update the ‘Caption’ property of the progress bar, so that the progress can be displayed both visually and as text:

The main ‘gotcha’ that you are likely to encounter when using the Progress bar is that you will often be dealing with integer values when calculating progress – for example, fifty-five records processed out of a hundred. Look what happens when we use these integers to calculate the progress:

Why doesn’t the progress bar display correctly as it does here?:

The reason for this is nothing to do with LINQPad or the ProgressBar utility – it is to do with c# arithmetic functionality. In c#, if you perform arithmetic on two integers, the result will be an integer, as we can see from the following LINQPad screenshots.

Dividing two integers gives an integer result:

Making one of the numbers a float produces output as a float:

For this reason, we must always cast at least one of the numbers we are basing our progress on as a float or a double in order for our progress bar to render correctly.

Here is a script (also available via InstantShare) which demonstrates the use of both the Fraction and Percent progress measures, and also a dynamic update of the caption whilst the script is running which will give you an output like this:

void Main()
{
	DisplayProgress(32);
	DisplayProgressPercent(76);
	Console.WriteLine("Done");
}

private void DisplayProgress(float steps) 
{	
	var pb = new Util.ProgressBar("Initialising....");
	pb.Dump();
	Thread.Sleep(2000);
		
	for (int i = 1; i < steps+1; i++)
	{		
		pb.Caption = "Completed " + i + " out of " + steps;
		pb.Fraction = i / steps;
		Thread.Sleep(50);
	}
}


private void DisplayProgressPercent(float steps)
{
	var pb = new Util.ProgressBar("Initialising....");
	pb.Dump();
	Thread.Sleep(2000);

	for (int i = 1; i < steps + 1; i++)
	{
		double percent = (i / steps) * 100;
		pb.Caption = "Completed " + percent + "%";
		pb.Percent = (int)percent;
		Thread.Sleep(100);
	}
}

LINQPad also has a utility called Util.Progress. By setting this to a value between 1 and 100, you can set the display of the progress bar at the bottom of the LINQPad IDE.
The script below demonstrates this functionality, as well as using a ‘DumpContainer’ which allows you to repeatedly dump output to a fixed point on the results pane:

DumpContainer dc = new DumpContainer();
dc.Dump();
for (int i = 0; i < 100; i++)
{	
	dc.Content = i;
	Util.Progress = i;
	Thread.Sleep(100);
}

Once you get the hang of it, using the progress utilities can be a very handy way to visualise the progress of long-running scripts.

Posted in LINQPad | Tagged | Leave a comment

Leave a Reply