Sunday, July 14, 2013

Progress of a Task in C#

By default Task doesn’t report it’s progress as a BackgroundWorker does. But that doesn’t mean we can’t get a progress of a Task. There is a new interface which was introduced with .NET framework 4.5 which is IProgress<T>. This interface exposes a Report(T) method, which the async task calls to report progress.

Let’s go by an example. I have the following async method.
async Task MyMethodAsync(int sleepTime, IProgress<MyTaskProgressReport> progress)
    int totalAmount = 10000; 

    for (int i = 0; i <= totalAmount;)
        await Task.Delay(sleepTime);
        progress.Report(new MyTaskProgressReport { CurrentProgressAmount = i, TotalProgressAmount = totalAmount, CurrentProgressMessage = string.Format("On {0} Message", i) });
        i = i + sleepTime;
It takes a progress parameter which is a IProgress of type “MyTaskProgressReport” and here is my “MyTaskProgressReport” class.
public class MyTaskProgressReport
   //current progress
   public int CurrentProgressAmount { get; set; }
   //total progress
   public int TotalProgressAmount { get; set; }
   //some message to pass to the UI of current progress
   public string CurrentProgressMessage { get; set; }
To simulate a time taking task, inside my async method, I have a For loop and inside it I have a Task Delay. In every iteration, progress is reported to the caller. Now let’ see how UI captures this.

On the UI thread, we have to define an event handler Action<T>, which will be called when IProgress<T>.Report is invoked.
private void ReportProgress(MyTaskProgressReport progress)
    label1.Text = progress.CurrentProgressMessage;
    textBox1.Text = string.Format("{0} out of {1}", progress.CurrentProgressAmount, progress.TotalProgressAmount);
Now I am going to call my async method. I have created a Progress<T> instance and invoked the async method, which is triggered by a button click.
private async void button1_Click(object sender, EventArgs e)
    var progressIndicator = new Progress<MyTaskProgressReport>(ReportProgress);
    await MyMethodAsync(1000, progressIndicator);
Here is the output,
I have uploaded a full sample to my SkyDrive. Do check it out.

Happy Coding.


1 comment:

  1. A nice eduction for me, never knew about existence of some thing like this. Though I am a VB.Net programmer, I could understand most of it.