{
public static void EachParallel<T>(this IEnumerable<T> list, Action<T> action)
{
int count = list.Count();
if (count == 0)
return;
else if (count == 1)
{
// Si un seul élément est présent, on l'exécute directement sans
// risquer de perde du temps pour la création des threads si aucun
// n'est disponible dans le pool
action(list.First());
}
else
{
// La méthode WaitHandle.WaitAll peut gérer au maximum 64 threads
int maxWaitHandler = count > 64 ? 64 : count;
// Initialisation des reset events pour connaitre les états
ManualResetEvent[] resetEvents = new ManualResetEvent[maxWaitHandler];
// On parcours la liste des éléments pour effectuer l'action sur
// chacun
int i = 0;
foreach (T item in list)
{
int index = i;
T itemCourant = item;
if (i >= maxWaitHandler)
// Si on dépasse la capacité maximum, on attends la libération
// d'une place
index = WaitHandle.WaitAny(resetEvents);
resetEvents[index] = new ManualResetEvent(false);
// Exécution du traitement
ThreadPool.QueueUserWorkItem(new WaitCallback((object data) =>
{
// Execution de la méthode
action(itemCourant);
// On informe que le traitement est terminé
resetEvents[index].Set();
}));
i++;
}
// On attend que tous les threads aient terminés
WaitHandle.WaitAll(resetEvents);
}
}
}