You can use Task.WhenAll
on an array of Tasks: https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.whenall?view=netframework-4.8
Creates a task that will complete when all of the supplied tasks have completed.
Here's an example of what I mean:
var tasks = new List<Task>();
using (WebClient client = new WebClient())
{
foreach (string url in urlList)
{
tasks.Add(client.DownloadData(url)));
}
await Task.WhenAll(tasks);
}
This will essentially start all of the requests then wait for them all to complete before carrying on, means that you're not making one request, waiting, making a second request, waiting, etc....
Just some notes about your code:
You should not return void when doing asyncronous code
Here's some information: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/async-return-types#BKMK_VoidReturnType
You use the void return type in asynchronous event handlers, which require a void return type. For methods other than event handlers that don't return a value, you should return a Task instead, because an async method that returns void can't be awaited. Any caller of such a method must be able to continue to completion without waiting for the called async method to finish, and the caller must be independent of any values or exceptions that the async method generates.
HttpClient is the new API
WebClient
I think is the old way of doing things? C# moves quickly these days: https://stackoverflow.com/a/23959136/1703915 it has similar performance and you can use it in a very similar way
You should probably check status code rather than catching exceptions
I could write an essay about allowing exceptions to create a control flow, but for now let's keep it simple, http status codes have a way of determining whether they are successful or not - use them.
Hope this helps