Vai al contenuto

Speed up loop with ForEachAsync

Scritto da:


I’m reposting an useful old post by Stephen Toub.

ForEach loop doesn’t supports Async/Await operators. If you like the possibility to have a foreach loop that can run in parallel, and can also leverage async/await operators to improve the performances of your loop, you can use the following, very useful, extension method.

public static class Extensions 
    public static Task ForEachAsync<TSource, TResult>(
        this IEnumerable<TSource> source,
        Func<TSource, Task<TResult>> taskSelector, Action<TSource, TResult> resultProcessor)
        var oneAtATime = new SemaphoreSlim(initialCount:1, maxCount:1);
        return Task.WhenAll(
            from item in source
            select ProcessAsync(item, taskSelector, resultProcessor, oneAtATime));

    private static async Task ProcessAsync<TSource, TResult>(
        TSource item,
        Func<TSource, Task<TResult>> taskSelector, Action<TSource, TResult> resultProcessor,
        SemaphoreSlim oneAtATime)
        TResult result = await taskSelector(item);
        await oneAtATime.WaitAsync();
        try { resultProcessor(item, result); }
        finally { oneAtATime.Release(); }


var collection = new List<object>();

await collection.ForEachAsync(
    async obj => { ... loop code, containing the await operators and a return statement ... },
    (obj, result) => { ...action to perform with the result of the operation... });


var client = new MyAsyncServiceClient();
var requestUrls = new List<string>();
var responseList = new List<Response>();

await requestUrls.ForEachAsync(
    async requestUrl => {
        var response = await client.ExecuteRequest(requestUrl);
        return response;
    (requestUrl, response) => { 

You can find here the original article, and here an useful post that explains the reasons behind the architectural choices.

Thanks Stephen!

Articolo precedente

D365 welcomes PowerApps Monitor

Unisciti alla discussione

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *