Task.Run and UI Progress Updates

Alex Strickland picture Alex Strickland · Feb 10, 2015 · Viewed 27.2k times · Source

This code snippet is from Stephen Cleary's blog and gives an example of how to report progress when using Task.Run. I would like to know why there are no cross thread issues with updating the UI, by which I mean why is invoke not required?

private async void button2_Click(object sender, EventArgs e)
{
    var progressHandler = new Progress<string>(value =>
    {
        label2.Text = value;
    });
    var progress = progressHandler as IProgress<string>;
    await Task.Run(() =>
    {
        for (int i = 0; i != 100; ++i)
        {
            if (progress != null)
                progress.Report("Stage " + i);
            Thread.Sleep(100);
        }
    });
    label2.Text = "Completed.";
}

Answer

Gusdor picture Gusdor · Feb 10, 2015

Progress<T> catches the current SynchronisationContext when it is instantiated. Whenever you call Report, it secretly delegates that to the captured context. In the example, the captured context is the UI, meaning that no exceptions occur.