I have a file with around 8000 employee records that I need to process by calling an rest API for each record. The sequential API calls are taking a lot of time, so I want to call them asynchronously in tasks and wait for all tasks to finish. I plan to have three tasks running at a time.
I have written the following code, but I'm concerned about race conditions or multi-threading problems since I am updating the employee entity inside the task. My understanding is I can update the entities but cannot call dbcontext methods. I know that the DBContext is not thread safe, so I am calling SaveChanges
outside of the task loop. Can anyone review my code and let me know if I'm doing it right? Here's my pseudo code:
private async TempMethod()
{
var dbcontext = new DBContext();
var employees = dbcontext.Employees.ToList();
var allTasks = new List<Task<APIResult>();
var throttler = new SemaphoreSlim(initialCount: 3);
foreach (var employee in employees)
{
await throttler.WaitAsync();
allTasks.Add(
Task.Run(async () =>
{
try
{
var apiResult = await apiClient.Update(employee);
if (apiResult == "Success")
{
employee.lastupdatedby = "Importer";
}
apiResult.recordNumber = employee.recordNumber;
return apiResult;
}
finally
{
throttler.Release();
}
}
);
}
var results = await Task.WhenAll(allTasks);
foreach (var result in results)
{
dbcontext.APIResults.Add(result);
}
//Save both Updated Employee and the Result entitities.
dbcontext.SaveChangesAsync();
}