Process List asynchronously with SemaphoreSlim for throttling extension method
The only thing I can see is that you should dispose the semaphore:

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


And you could generalize to IEnumerable&lt;T&gt; instead of IList&lt;T&gt;



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

public static void ProcessWithParallelAsync&lt;T&gt;(this IEnumerable&lt;T&gt; list, Action&lt;T&gt; 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&lt;T&gt;(this IEnumerable&lt;T&gt; list, Action&lt;T&gt; action, int maxConcurrency)
{
  return Task.Run(() =&gt;
  {
    ParallelOptions options = new ParallelOptions();
    options.MaxDegreeOfParallelism = maxConcurrency;

    Parallel.ForEach(list, options, action);
  });
}