I'm trying to make 4,000+ database calls run simultaneously. But what I'm finding is that instead, all of them will stack up, and none of them will finish until all of them have started.
What I'm trying so far is based on this thread:
Process thousands of database calls simultaneously
The logic works perfectly when it's done in a console app with no database call. But here, it's behaving as I described above.
using Dapper;
public async Task ProcessFileAsync(Stream blobFile)
{
List<Customer> customers = LoadCustomers(blobFile)
var tasks = RunWithMaxDegreeOfConcurrency(10, customers, customer => VerifyCustomerAsync(customer));
await Task.WhenAll(tasks);
DoStuffWhenAllDatabaseCallsAreFinished()
}
private async Task VerifyCustomerAsync(Customer customer)
{
RecordLog(LogType.Info, $"Starting {customer.CustomerName}");
var parameters = new DynamicParameters();
// ... create parameters
ValidaitonResult validaitonResult = null;
using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["FubarConnection"].ConnectionString))
{
connection.Open();
var queryResult = await connection.QueryAsync<ValidaitonResult>("sp_name", parameters, commandType: CommandType.StoredProcedure);
validaitonResult = queryResult.FirstOrDefault();
}
// Handle the result
switch (validaitonResult.ValidaitonAction)
{
case ValidaitonAction.NoAction:
_customersNoAction.Add(customer);
break;
case ValidaitonAction.Insert:
_customersToInsert.Add(customer);
break;
default:
break;
}
RecordLog(LogType.Info, $"Finished {customer.CustomerName}");
}
private static async Task RunWithMaxDegreeOfConcurrency<T>(int maxDegreeOfConcurrency, IEnumerable<T> collection, Func<T, Task> taskFactory)
{
var activeTasks = new List<Task>(maxDegreeOfConcurrency);
foreach (var task in collection.Select(taskFactory))
{
activeTasks.Add(task);
if (activeTasks.Count == maxDegreeOfConcurrency)
{
await Task.WhenAny(activeTasks.ToArray());
activeTasks.RemoveAll(t => t.IsCompleted);
}
}
await Task.WhenAll(activeTasks.ToArray()).ContinueWith(t =>
{
//observe exceptions in a manner consistent with the above
});
}