I already read all those posts:
Reporting progress from Async Task
https://devblogs.microsoft.com/dotnet/async-in-4-5-enabling-progress-and-cancellation-in-async-apis/
https://blog.stephencleary.com/2012/02/reporting-progress-from-async-tasks.html
But still I don't know how to report a Progress from many Tasks when I'm using await Task.WhenAll(tasks);
So, I am using this code:
public string StatusMessage { get; set; }
public async void ButtonClickHandler(object sender, EventArgs e)
{
var tasks = new List<Task>
{
Task1,
Task2,
Task3,
Task4,
Task5
};
await Task.WhenAll(tasks);
}
So I want to get a change in StatusMessage
when any on Task1..Task5
is completed. Somehow each task has to have a name and that name to be reported to StatusMessage
variable.
I want also an event to rise when StatusMessage
changes.
StatusMessage
could be also a cumulative list or barely a string.
JSteward post from here it is interesting but I don't know how to convert my Task1..Task5 tasks in a WorkItem
from his sample.
How can I do that?
You could define an extension method on the Task
type, that reports progress on an IProgress<T>
when the task completes successfully:
public static async Task OnSuccessfulCompletion<T>(
this Task task, IProgress<T> progress, T progressValue)
{
ArgumentNullException.ThrowIfNull(task);
ArgumentNullException.ThrowIfNull(progress);
await task.ConfigureAwait(false);
progress.Report(progressValue);
}
And use it like this:
public async void ButtonClickHandler(object sender, EventArgs e)
{
/* Launching the tasks Task1, Task2 etc is omitted */
Progress<string> progress = new(value => textBox1.AppendText($"{value}\r\n"));
List<Task> tasks = new()
{
Task1.OnSuccessfulCompletion(progress, "Task1"),
Task2.OnSuccessfulCompletion(progress, "Task2"),
Task3.OnSuccessfulCompletion(progress, "Task3"),
Task4.OnSuccessfulCompletion(progress, "Task4"),
Task5.OnSuccessfulCompletion(progress, "Task5"),
};
await Task.WhenAll(tasks);
}
Be aware that the Progress<T>
type reports progress asynchronously. This means that the handler
might be invoked after the completion of the ButtonClickHandler
method. If you write anything directly on the textBox1
, immediately after the line await Task.WhenAll(tasks);
, this text might not be the last to be appended to the textBox1
. In case you don't like this behavior, you can find a synchronous IProgress<T>
implementation here.