OVH Cloud OVH Cloud

Patterns et multithreading

1 réponse
Avatar
Zim
Bonjour,

je suis à la recherche de patterns pour faire du multithreading.
Mon besoin est le suivant : j'ai en entrée une liste d'objets (liste
dont la taille varie),
je souhaite effectuer un traitement (assez long) identique à chacun de
ces objets, et pour gagner du temps je voudrais
faire du traitement en parallèle. Mais pour éviter d'exploser le besoin
en ressources, je souhaiterai ne lancer que n threads
simultanément (n étant un paramètre de configuration).
Mon problème est donc de ne lancer que n threads et de lancer traitement
suivant une fois que l'un des threads en cours est terminé.

En lisant des docs à droite à gauche, il est apparement déconseillé
d'utiliser le ThreadPool .NET pour des traitements longs.
Je me suis donc dis qu'il serait mieux d'écrire mon propre pool de
threads (une version simplifiée, cela va de soi) :

class ThreadPool
{
private Thread[] threads;
public ManualResetEvent[] EV;
private int maxInstances;

public ThreadPool(int MaxInstances)
{
maxInstances = MaxInstances;
threads = new Thread[MaxInstances];
EV = new ManualResetEvent[MaxInstances];

for(int i=0; i<maxInstances; i++)
{
EV[i] = new ManualResetEvent(true);
}
}

public int GetThread()
{
Thread.Sleep(100);
for(int i=0; i<maxInstances; i++)
{
if(threads[i]==null||threads[i].ThreadState==ThreadState.Stopped)
{
return i;
}
}

return -1;
}

public ManualResetEvent Execute(ThreadStart start, int index)
{
EV[index].Reset();
threads[index] = new Thread(start);
threads[index].Start();

return EV[index];
}
}

J'ai crée un tableau de Threads et un tableau de ManualResetEvents.
J'appelle GetThread pour obtenir l'index d'un Thread libre (la présence
du Sleep m'ennuie un peu, mais je suis obliger de
temporiser pour être certain que les threads terminés soient bien à
l'état Stopped). Et pour exécuter la tâche, j'utilise la méthode Execute.

Le code utilisant cette classe donne ceci :
ThreadPool pool = new ThreadPool(10); // 10 étant le nombre de threads
allouables
for(int i=0; i<15; i++)
{
MonObjet obj = new MonObjet();
int th = pool.GetThread();
obj.EV = pool.Execute(new ThreadStart(t.Start), th);

AutoResetEvent.WaitAny(pool.EV);
}
AutoResetEvent.WaitAll(pool.EV);
Console.WriteLine("Terminé");

MonObjet possède une référence vers le ManualResetEvent lié au thread et
le "set" en fin de tâche.
Ce code fonctionne, cependant je reste persuadé qu'il y a beaucoup
mieux, et que des patterns existent. Malheureusement,
j'ai trouvé peu de documentation là-dessus.
Si quelqu'un pouvait m'éclairer, je le remercie d'avance.

Cordialement,
Zim.

1 réponse

Avatar
Alexis KARTMANN
L'ideal pour la gestion d'un pool de thread est d'utiliser des IOCP.
Regarde cet article
http://www.devarticles.com/c/a/C-Sharp/IOCP-Thread-Pooling-in-C-sharp-Part-I/
qui montre comment le faire en CSharp