# Process List asynchronously with SemaphoreSlim for throttling extension method

I've got some methods that follow a similar pattern, and wanted to abstract some of the logic away into an extension method. Specifically, I am processing lists of objects with the TPL, and throttling that processing with a SemaphoreSlim.

public static Task ValidateProxiesAsync(IList<Proxy> proxies, IList<ProxyJudge> judges, IList<ProxyTest> tests)
{
{
await ValidateTestsAsync(judges.ToList<IProxyTest>());
await ValidateTestsAsync(tests.ToList<IProxyTest>());
var semaphore = new SemaphoreSlim(100);
foreach (var proxy in proxies)
{
await semaphore.WaitAsync();
{
proxy.Status = proxy.TestValidity(judges[0]);
semaphore.Release();
}));
}
});
}

{
{
var semaphore = new SemaphoreSlim(100);
foreach (var test in tests)
{
await semaphore.WaitAsync();
{
test.Status = test.TestValidity();
semaphore.Release();
}));
}
});
}


I wrote this extension method to reduce the LOC needed to do this. But I wanted to make sure I didn't overlook something. Perhaps there is a better solution that someone on here could suggest (TPL Dataflow?).

Extension method:

    public static Task ProcessWithSemaphoreAsync<T>(this IList<T> list, Action<T> action, int maxConcurrency)
{
var semaphore = new SemaphoreSlim(maxConcurrency);
foreach (var item in list)
{
await semaphore.WaitAsync();
{
action.Invoke(item);
semaphore.Release();
}));
}
});
}


The only thing I can see is that you should dispose the semaphore:

using (var semaphore = new SemaphoreSlim(maxConcurrency))
{
}


And you could generalize to IEnumerable<T> instead of IList<T>

A simple solution using Parallel.ForEach() could be:

public static void ProcessWithParallelAsync<T>(this IEnumerable<T> list, Action<T> action, int maxConcurrency)
{
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = maxConcurrency;
Parallel.ForEach(list, options, action);
}


Or you could wrap it in a Task if you like:

public static Task ProcessWithParallelAsync<T>(this IEnumerable<T> list, Action<T> action, int maxConcurrency)
{