Reputation: 70
We have a WebAPI Service (.NET Framework 4.7.2) that returns a list of records to the consumer.
In the beginning, to build the list, the controller made 2 synchronous web service calls to external systems using a service client that doesn't support asynchronous calls.
Now, due to new requirements the controller has to make more than two WebService calls to the external systems.
Is it OK to offload the synchronous requests to parallel tasks using Task.Run to improve the response time? (Have the requests execute in parallel, rather than one after the other) The code that would do this looks like:
public async Task<IEnumerable<T>> FetchAllRecordsAsync(List<Query> queries)
{
List<T> fetchedRecords = new List<T>();
List<Task<IEnumerable<T>>> fetchRecordsTasksCollection = new List<Task<IEnumerable<T>>>();
foreach (var query in queries)
{
//Calling the Synchronous Web Service Call
fetchRecordsTasksCollection.Add(Task.Run(() => FetchAllRecords(query)));
}
var results = Task.WhenAll(fetchRecordsTasksCollection.ToArray());
await results;
if (results.Status != TaskStatus.RanToCompletion)
throw new Exception("Failed to fetch records");
foreach (var result in fetchRecordsTasksCollection)
{
fetchedRecords.AddRange(await result);
}
return fetchedRecords;
}
Or is there a better way to do this?
References : https://devblogs.microsoft.com/pfxteam/should-i-expose-asynchronous-wrappers-for-synchronous-methods/
Thank you for your help!
Upvotes: 0
Views: 488
Reputation: 5496
This is a good question.
Ideally, I would imagine that FetchAllRecords
would be doing work that is IO bound, like talking to a database or some other server, so it would be async and return a Task
, I would start with investigating why this isn't the case, is it blocking on async work?
With that out of the way, I will assume FetchAllRecords
does some work that takes more than a few milliseconds. Now you have a trade off to make, do you want a request that comes in to have the lowest possible latency? I which case a couple fo Task.Run
will give you parallel work, which is a little more optimal latency wise.
However, you are using thread pool threads to achieve this, now any 1 request that comes in maybe using up to 2 threads at a time. For scalability reasons, this is something you usually want to avoid, as it can limit the overall efficiency of your service on that particular server. This is directly opposed to goal that async tries to achieve. If this is a server that doesn't serve many requests, perhaps that doesn't matter, this is your call.
So it depends 🙂
Upvotes: 3