8.17Parallel Requests (Batch Downloads)

Created on Aug 17, 2026~2 min read

In scenarios where multiple HTTP requests need to be sent simultaneously (such as batch downloads, concurrently calling multiple APIs, mixing the execution of different types of requests, etc.), you can use the framework's built-in ParallelUtility utility class, which provides a more concise API and supports controlling the maximum degree of concurrency.

Concurrently Executing the Same Operation on a Collection

Use ParallelUtility.ForEachAsync to concurrently execute the same asynchronous operation on each element of a collection:

cs
var urls = new[]{    "https://furion.net/api/users",    "https://furion.net/api/orders",    "https://furion.net/api/products"};// Concurrent requests, default maximum degree of concurrency is 4var results = await ParallelUtility.ForEachAsync(urls, async (url, token) =>{    return await _httpRemoteService.GetAsStringAsync(url, cancellationToken: token);});// results are returned in the original collection order

You can also control the maximum degree of concurrency via the maxDegreeOfParallelism parameter:

cs
await ParallelUtility.ForEachAsync(urls, async (url, token) =>{    await _httpRemoteService.GetAsStringAsync(url, cancellationToken: token);}, maxDegreeOfParallelism: 2);   // Execute at most 2 requests concurrently

Concurrently Executing Multiple Different Operations

When you need to simultaneously execute multiple different types of operations, use ParallelUtility.RunAsync:

cs
// Concurrently execute multiple different requests; all operations run simultaneouslyawait ParallelUtility.RunAsync(    token => _httpRemoteService.GetAsStringAsync("https://furion.net/api/users", cancellationToken: token),    token => _httpRemoteService.PostAsStringAsync("https://furion.net/api/orders", "\"Furion\"", cancellationToken: token),    token => _httpRemoteService.DownloadFileWithConsoleProgressAsync("https://furion.net/logo.png", @"C:\Workspaces\", FileExistsBehavior.Overwrite, cancellationToken: token));

If you need to obtain the return values, you can use the generic overload:

cs
var results = await ParallelUtility.RunAsync(    async token => await _httpRemoteService.GetAsStringAsync("https://furion.net/api/users", cancellationToken: token),    async token => await _httpRemoteService.GetAsStringAsync("https://furion.net/api/orders", cancellationToken: token),    async token => await _httpRemoteService.GetAsStringAsync("https://furion.net/api/products", cancellationToken: token));// results[0], results[1], results[2] correspond to the results of each operation in the order passed in