Search code examples
c#async-awaittaskwebrequest

Are these webrequests actually concurrent?


I have a UrlList of only 4 URLs which I want to use to make 4 concurrent requests. Does the code below truly make 4 requests which start at the same time?

My testing appears to show that it does, but am I correct in thinking that there will actually be 4 requests retrieving data from the URL target at the same time or does it just appear that way?

    static void Main(string[] args)
    {
        var t = Do_TaskWhenAll();
        t.Wait();
    }

    public static async Task Do_TaskWhenAll()
    {
        var downloadTasksQuery = from url in UrlList select Run(url);

        var downloadTasks = downloadTasksQuery.ToArray();

        Results = await Task.WhenAll(downloadTasks);
    }

    public static async Task<string> Run(string url)
    {
        var client = new WebClient();
        AddHeaders(client);

        var content = await client.DownloadStringTaskAsync(new Uri(url));

        return content;
    }

Solution

  • Correct, when ToArray is called, the enumerable downloadTasksQuery will yield a task for every URL, running your web requests concurrently.

    await Task.WhenAll ensures your task completes only when all web requests have completed.

    You can rewrite your code to be less verbose, while doing effectively the same, like so:

    public static async Task Do_TaskWhenAll()
    {
        var downloadTasks = from url in UrlList select Run(url);
    
        Results = await Task.WhenAll(downloadTasks);
    }
    

    There's no need for ToArray because Task.WhenAll will enumerate your enumerable for you.

    I advice you to use HttpClient instead of WebClient. Using HttpClient, you won't have to create a new instance of the client for each concurrent request, as it allows you to reuse the same client for doing multiple requests, concurrently.