I have some c# code (MVC WebAPI) which iterates over an array of IDs in parallel and makes an API call for each entry. In the first version, the whole code was a simple, synchronous for loop. Now we changed that to a combination of Task.WhenAll and a LINQ select:
private async Task RunHeavyLoad(IProgress<float> progress) {
List<MyObj> myElements = new List<MyObj>(someEntries);
float totalSteps = 1f / myElements.Count();
int currentStep = 0;
await Task.WhenAll(myElements.Select(async elem => {
var result = await SomeHeavyApiCall(elem);
DoSomethingWithThe(result);
progress.Report(totalSteps * System.Threading.Interlocked.Increment(ref currentStep) * .1f);
}
// Do some more stuff
}
This is a simplified version of the original method! The actual method EnforceImmediateImport
is called by this SignalR hub method:
public class ImportStatusHub : Hub {
public async Task RunUnscheduledImportAsync(DateTime? fromDate, DateTime? toDate) {
Clients.Others.enableManualImport(false);
try {
Progress<float> progress = new Progress<float>((p) => Clients.All.updateProgress(p));
await MvcApplication.GlobalScheduler.EnforceImmediateImport(progress, fromDate, toDate);
} catch (Exception ex) {
Clients.All.importError(ex.Message);
}
Clients.Others.enableManualImport(true);
}
}
Now I wonder, if this is "thread safe" per se, or if I need to do something with the progress.Report
calls to prevent anything from going wrong.