The Task Parallel Library Sampler – Part 5: Running and working with the TPL samples

Part One: Starting with MVVM
Part Two: The MVVM solution structure and basic framework
Part Three: Base Classes
Part 4: Sampler View, View Model and Model

There is a new version of the solution available.

Finally, before getting in the actual TPL samples there is one last thing to cover. How do we run the samples? Well, as previously discussed the Submit button in SamplerView is bound to the SamplerViewModel.Submit().

public async void Submit()
{
	CurrentState = "Running";
	await Sampler.RunSamples();
	CurrentState = "Completed";
}

Using async/await, the model then runs the samples in the model via Sampler.RunSamples(). The async/await is critical here so the UI isn’t locked while the samples are run.

Here is Sampler.RunSamples()

public async Task RunSamples()
{
	await Task.Run(() =>
	{
		System.Drawing.Bitmap bmp = null;
		foreach (var sample in Samples)
		{
			if(!sample.IsEnabled)
				continue;

			if (sample.ImageRequired)
			{
				UpdateResults("Reseting Image");
				ResetDestinationImage();
				bmp = GetBitmapFromDestinationImage();
			}
			UpdateResults("Starting " + sample.SampleName);
			sample.Run(bmp, UpdateResults);
			UpdateResults("Completed " + sample.SampleName);
			UpdateResults(sample.SampleName + " ran in " + sample.RunTime.ToString() + Environment.NewLine);
		}

		if (bmp != null)
		{
			SetDestinationImageFromBitmap(bmp);
		}
	});
}

private void UpdateResults(string result)
{
	Results += result + Environment.NewLine;
}

The async keyword in the method declaration is what allows the ViewModel to run this method asynchronously. In order to define a method as asynchronous, it must contain an await call. To do this I call Task.Run with an await so the framework knows to spin off a thread and wait for it to return. There’s a bit more than that but I’ll discuss async/await in more detail in the TPL sample for it.

The really interesting thing here is passing the “UpdateResults” method into the run method of the sample model. You’ll recall in the “base classes” post that the abstract sample model takes a bitmap and Action<string>. The SamplerView has a text box that is bound to the Results property of our Sampler model. This way we can get real-time updating from the samples as they run. Since their running in their own thread (via the await Task.Run) it won’t block the UI and the binding takes care of invoking the update to the text so that it happens on the main thread without having to worry about updating the UI on the wrong thread.

And that’s it. It’s pretty simple. Next up I’ll go over the first three samples included in the solution that demonstrate when to and when not to use Parallel.For (and by extension Parallel.ForEach).

Thanks,
Brian

Leave a Reply