Async Samples 4: Reporting progress

The next async samples explore how to report progress while async operations execute.

There’s only one sample here, but it’s somewhat more involved.  The client method (calling async methods) method follows:

        public async Task AsyncProgressPolling()
{
cts = new CancellationTokenSource();
var progress = new EventProgress<GetAllPingsPartialResult>();

try
{
progress.ProgressChanged += (source, e) =>
{
ProgressBar.Value = e.Value.Count % 100;
};
foreach (var item in await GetAllPingsAsync(cts.Token, progress))
{
Console.WriteLine(item);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation canceled.");
}
}
 
The new code creates an EventProgress<T> object. This object supports a ProgressChanged event that enables the worker tasks to report progress as their tasks progress. When the event is raised, the progress bar moves ahead.
 
The other side of this convention is to write the code that runs the background operation in such a way that it raises those events as it progresses. Here’s the code that runs the background tasks, and raises that progress event:
 
        public async Task<string[]> GetAllPingsAsync(
CancellationToken cancel, IProgress<GetAllPingsPartialResult> progress)
{
var sites = new List<string>();
for (int i = 0; i < 30; i++)
{
sites.Add("http://www.microsoft.com");
sites.Add("http://msdn.microsoft.com");
sites.Add("http://www.xbox.com");
}
var results = new List<string>(sites.Count);
foreach (var site in sites)
{
cancel.ThrowIfCancellationRequested();
var time = DateTime.UtcNow;
try {await new WebClient().DownloadStringTaskAsync(site);}
catch {}
var ms = (DateTime.UtcNow - time).TotalMilliseconds;
results.Add(String.Format("[{0}] {1}", ms, site));
if (progress != null)
progress.Report(new GetAllPingsPartialResult()
{
Pings = new ReadOnlyCollection<string>(results),
Count = results.Count
});
}
return results.ToArray();
}

This method contains the familiar event source pattern.
As this method does its work, it raises the Progress event by calling progress.Report(), passing it the current results, and the count of the results.
 

Key Points

Methods designed to be run asynchronously should consider supporting progress reporting. There’s a standard way to do it, and you only report progress to those callers that ask for it.
Client code can ask for progress using the same mechanism.
Created: 3/15/2011 11:43:51 AM

Current Projects

I create content for .NET Core. My work appears in the .NET Core documentation site. I'm primarily responsible for the section that will help you learn C#.

All of these projects are Open Source (using the Creative Commons license for content, and the MIT license for code). If you would like to contribute, visit our GitHub Repository. Or, if you have questions, comments, or ideas for improvement, please create an issue for us.

I'm also the president of Humanitarian Toolbox. We build Open Source software that supports Humanitarian Disaster Relief efforts. We'd appreciate any help you can give to our projects. Look at our GitHub home page to see a list of our current projects. See what interests you, and dive in.

Or, if you have a group of volunteers, talk to us about hosting a codeathon event.