OVH Cloud OVH Cloud

Questions sur le Multithread...

5 réponses
Avatar
Jérôme Quintard
Salut à tous,

Je dois développer une application genre mailinglists. J'utilise dans mon
application plusieurs threads qui eux même instancies plusieurs threads.
Mais voilà patatra les ressources CPU sont horiblement solicités. Voici la
logique que j'ai mis en place. Merci de corriger mes erreurs et si possible
de répondre à mes intérrogations...:)

- Un thread Queues. Ce thread regarde dans une table SQLServer, si il y a
des envois à effectuer. Il tourne indéfiniment avec une boucle de type
while=true et un sleep de 1 seconde. Si il y a de nouveaux envois, je mets
dans une collection nommé QUEUE de type queue, l'id des messages à envoyer.

Un thread Queue. Ce thread boucle aussi indéfiniment sur une boucle
while=true mais sans sleep. Si ma collection QUEUE contient des éléments
elle les dequeues un par un pour les traiter en récupérant la liste des
utilisateurs pour l'id du message courant que je charge ensuite dans une
collection nommée USERS de type queue. Une fois la liste des utilisateurs
récupéré je démarre 20 thread Smtp chargé de faire l'envoi du message. Au
final je dequeue QUEUE de l'id du message traité.

20 threads Smtp qui se charge de l'envoi du message. Le thread à une boucle
while sur le count de ma collection USERS. Tant que la collection USERS
n'est pas vidée, je dequee chaque élémént que j'envoi par la suite.

Hierarchiquement ça donne ça :

Queues
Queue
Smtp1
Smtp2
...
Smtp20

Logiquement si j'ai compris je devrais faire ça : Laisser la boucle
perpetuelle sur Queues qui à mon avis est obligatoire. Sur queue, je devrais
démarrer le thread, regarder si la collection QUEUE possède des données, les
traiters et passer finalement en mode Suspend. Si des messages arrivent dans
Queues, je devrai dans ce cas résumé le thread. Pour les threads Smtp, je
devrais je suppose faire un join pour bloquer le thread Queue tant que tous
les mails ne sont pas partis.

Mes petites questions ...

Lorsque je passe Queue en suspend et que j'essai de le résumer, j'ai une
erreur car il ne serait pas démarrer... Queue est pourtant toujours
instancié...

Comment connaître dans un thread Smtp, le numéro du thread Smtp en cours,
pour pouvoir pour afficher un debug par exemple.

Comment faire un join avec les 20 threads (en fait je donne 20 mais le
nombre est paramètrable) ?

Est-que ma logique est la bonne ou est-ce qu'il y a un truc qui coince ??

Merci

Jérôme

5 réponses

Avatar
Paul Bacelar
Laissez tomber immédiatement toutes vos boucles actives.

Il y a toujours un moyen pour ne pas avoir ces horreurs.

Pensez aussi au Threading Pool intégré à la CLR .NET qui permet d'optimiser
le nombre de thread en fonction du nombre de CPU ou de pseudo-CPU de votre
système hôte.
--
Paul Bacelar


"Jérôme Quintard" wrote in
message news:#
Salut à tous,

Je dois développer une application genre mailinglists. J'utilise dans mon
application plusieurs threads qui eux même instancies plusieurs threads.
Mais voilà patatra les ressources CPU sont horiblement solicités. Voici la
logique que j'ai mis en place. Merci de corriger mes erreurs et si


possible
de répondre à mes intérrogations...:)

- Un thread Queues. Ce thread regarde dans une table SQLServer, si il y a
des envois à effectuer. Il tourne indéfiniment avec une boucle de type
while=true et un sleep de 1 seconde. Si il y a de nouveaux envois, je mets
dans une collection nommé QUEUE de type queue, l'id des messages à


envoyer.

Un thread Queue. Ce thread boucle aussi indéfiniment sur une boucle
while=true mais sans sleep. Si ma collection QUEUE contient des éléments
elle les dequeues un par un pour les traiter en récupérant la liste des
utilisateurs pour l'id du message courant que je charge ensuite dans une
collection nommée USERS de type queue. Une fois la liste des utilisateurs
récupéré je démarre 20 thread Smtp chargé de faire l'envoi du message. Au
final je dequeue QUEUE de l'id du message traité.

20 threads Smtp qui se charge de l'envoi du message. Le thread à une


boucle
while sur le count de ma collection USERS. Tant que la collection USERS
n'est pas vidée, je dequee chaque élémént que j'envoi par la suite.

Hierarchiquement ça donne ça :

Queues
Queue
Smtp1
Smtp2
...
Smtp20

Logiquement si j'ai compris je devrais faire ça : Laisser la boucle
perpetuelle sur Queues qui à mon avis est obligatoire. Sur queue, je


devrais
démarrer le thread, regarder si la collection QUEUE possède des données,


les
traiters et passer finalement en mode Suspend. Si des messages arrivent


dans
Queues, je devrai dans ce cas résumé le thread. Pour les threads Smtp, je
devrais je suppose faire un join pour bloquer le thread Queue tant que


tous
les mails ne sont pas partis.

Mes petites questions ...

Lorsque je passe Queue en suspend et que j'essai de le résumer, j'ai une
erreur car il ne serait pas démarrer... Queue est pourtant toujours
instancié...

Comment connaître dans un thread Smtp, le numéro du thread Smtp en cours,
pour pouvoir pour afficher un debug par exemple.

Comment faire un join avec les 20 threads (en fait je donne 20 mais le
nombre est paramètrable) ?

Est-que ma logique est la bonne ou est-ce qu'il y a un truc qui coince ??

Merci

Jérôme




Avatar
Ambassadeur Kosh
comme file de message, on a revé mieux que SqlServer.
pensez aux Message Queue ou autre objets systemes globaux pour comuniquer
entre applis.
je me même demande si avec ADO, on peut pas se faire messager une
notification d'action sur une table...

que le sleep fasse 1 ou 20 secondes, vous faites de l'attente active, donc
forcément, c'est naze.
instanciez les thread au besoin. si ça depasse la quantité normale, faites
comme Paul a dit : un pool.
Avatar
llopht
Ambassadeur Kosh wrote:
comme file de message, on a revé mieux que SqlServer.
pensez aux Message Queue ou autre objets systemes globaux pour comuniquer
entre applis.
je me même demande si avec ADO, on peut pas se faire messager une
notification d'action sur une table...

que le sleep fasse 1 ou 20 secondes, vous faites de l'attente active, donc
forcément, c'est naze.
instanciez les thread au besoin. si ça depasse la quantité normale, faites
comme Paul a dit : un pool.





Merci,

Bon mon précédent message est passeé hors thread mais bon.. Ok, je vais
utiliser le pool de thread. Visiblement il faut que j'utilise
ThreadPool.RegisterWaitForSingleObject + WaitOrTimerCallback, c'est ça ?

Donc:

Queues sera démarré en indiquant que je veux réinitialiser le timer
interne du thread à 0

Queue sera démarré uniquement si il y a des données dans la collection.

Smtp sera démarré uniquement si il y a des données dans la collection.
Dans ce cas il suffit que je créé autant de thread que j'en ai besoin
(dans la limite des 25) ? Ne risque t'il pas d'y avoir de problème avec
le dequeue de ma collection USERS ?


Concernant SQLServer... pas le choix l'appli est dépendante d'un autre
système.

Merci

Jérôme
Avatar
Paul Bacelar
Commencer par le plus simple:
Notification depuis SQL Server 2000
http://msdn.microsoft.com/msdnmag/issues/02/11/SQLServerNotificationServices/default.aspx
--
Paul Bacelar

"llopht" wrote in message
news:
Ambassadeur Kosh wrote:
> comme file de message, on a revé mieux que SqlServer.
> pensez aux Message Queue ou autre objets systemes globaux pour


comuniquer
> entre applis.
> je me même demande si avec ADO, on peut pas se faire messager une
> notification d'action sur une table...
>
> que le sleep fasse 1 ou 20 secondes, vous faites de l'attente active,


donc
> forcément, c'est naze.
> instanciez les thread au besoin. si ça depasse la quantité normale,


faites
> comme Paul a dit : un pool.
>
>

Merci,

Bon mon précédent message est passeé hors thread mais bon.. Ok, je vais
utiliser le pool de thread. Visiblement il faut que j'utilise
ThreadPool.RegisterWaitForSingleObject + WaitOrTimerCallback, c'est ça ?

Donc:

Queues sera démarré en indiquant que je veux réinitialiser le timer
interne du thread à 0

Queue sera démarré uniquement si il y a des données dans la collection.

Smtp sera démarré uniquement si il y a des données dans la collection.
Dans ce cas il suffit que je créé autant de thread que j'en ai besoin
(dans la limite des 25) ? Ne risque t'il pas d'y avoir de problème avec
le dequeue de ma collection USERS ?


Concernant SQLServer... pas le choix l'appli est dépendante d'un autre
système.

Merci

Jérôme


Avatar
Lloyd Dupont
oublie: Suspend()
pense: AutoResetEvent

"Jérôme Quintard" wrote in
message news:%
Salut à tous,

Je dois développer une application genre mailinglists. J'utilise dans mon
application plusieurs threads qui eux même instancies plusieurs threads.
Mais voilà patatra les ressources CPU sont horiblement solicités. Voici la
logique que j'ai mis en place. Merci de corriger mes erreurs et si
possible
de répondre à mes intérrogations...:)

- Un thread Queues. Ce thread regarde dans une table SQLServer, si il y a
des envois à effectuer. Il tourne indéfiniment avec une boucle de type
while=true et un sleep de 1 seconde. Si il y a de nouveaux envois, je mets
dans une collection nommé QUEUE de type queue, l'id des messages à
envoyer.

Un thread Queue. Ce thread boucle aussi indéfiniment sur une boucle
while=true mais sans sleep. Si ma collection QUEUE contient des éléments
elle les dequeues un par un pour les traiter en récupérant la liste des
utilisateurs pour l'id du message courant que je charge ensuite dans une
collection nommée USERS de type queue. Une fois la liste des utilisateurs
récupéré je démarre 20 thread Smtp chargé de faire l'envoi du message. Au
final je dequeue QUEUE de l'id du message traité.

20 threads Smtp qui se charge de l'envoi du message. Le thread à une
boucle
while sur le count de ma collection USERS. Tant que la collection USERS
n'est pas vidée, je dequee chaque élémént que j'envoi par la suite.

Hierarchiquement ça donne ça :

Queues
Queue
Smtp1
Smtp2
...
Smtp20

Logiquement si j'ai compris je devrais faire ça : Laisser la boucle
perpetuelle sur Queues qui à mon avis est obligatoire. Sur queue, je
devrais
démarrer le thread, regarder si la collection QUEUE possède des données,
les
traiters et passer finalement en mode Suspend. Si des messages arrivent
dans
Queues, je devrai dans ce cas résumé le thread. Pour les threads Smtp, je
devrais je suppose faire un join pour bloquer le thread Queue tant que
tous
les mails ne sont pas partis.

Mes petites questions ...

Lorsque je passe Queue en suspend et que j'essai de le résumer, j'ai une
erreur car il ne serait pas démarrer... Queue est pourtant toujours
instancié...

Comment connaître dans un thread Smtp, le numéro du thread Smtp en cours,
pour pouvoir pour afficher un debug par exemple.

Comment faire un join avec les 20 threads (en fait je donne 20 mais le
nombre est paramètrable) ?

Est-que ma logique est la bonne ou est-ce qu'il y a un truc qui coince ??

Merci

Jérôme