In the previous post, we explored IProgress interface briefly and understood how it helps us in reporting progress. It seemed a perfect fit choice, with little chances of human errors. However, there are things one needs to be aware of to ensure you do not end up with unrecognizable errors.
Let’s rewrite the code in earlier post with slight modification.
async Task InvokeLongRunningMethod() { Console.WriteLine("Initiating method call"); var progress = new Progress<MessageObject>(ProgressDisplay); var result = await LongRunningMethod(progress); Console.WriteLine($"Completed executing method with result = {result}"); } void ProgressDisplay(MessageObject update) { Console.WriteLine(update.Message); } async Task<bool> LongRunningMethod(IProgress<MessageObject> progress) { var test = new MessageObject(); for(int i=0;i<100;i++) { if(i%10==0) { test.msg = $"In Progress : {i}%"; progress.Report(test); } } return true; } public class MessageObject { public string Message{get;set;} }
We have created a MessageObject Class, which has been passed on as the parameter for the IProgress interface parameter type T. So how does this change the equation. Let’s run the code and watch the output first.
Initiating method call Completed executing method with result = True In Progress : 90% In Progress : 90% In Progress : 90% In Progress : 90% In Progress : 90% In Progress : 90% In Progress : 90% In Progress : 90% In Progress : 90% In Progress : 90%
As observed in the output, the progress shows 90% each time. Isn’t that strange. Well, not quite if you think a bit more. The IProgress.Report method calls are asynchronous and needn’t be quite completed at that moment. Since the object instance changes before the Report method is called again, the previous call too ends with same value. For this very reason, you need to ensure that the T parameter type is always immutable or you create a separate copy each time Report is invoked.