|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | ||||
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Bonjour à tous!
Après plusieurs semaines de recherche, je pense baisser les bras avec les threads Problème : Je vais essayer résumer l'essentiel: Avant, je tiens à souligner que je n'ai aucun problème sur l'utilisation des threads ni aucune erreur mais seulement des résultats incohérents dont je n'arrive pas à trouver la raison. J'ai un gros fichier Hyperfile d'articles de l'ordre de plusieurs millions d'enregistrements. Pour chacun des articles, je fais une requete HTTP afin de vérifier sur un site web l'existence de l'article. Si elle n'existe pas sur le site je l'ajoute à une liste. La rubrique Done de ARTICLE permet de savoir si la requete a été effectué pour un article donné! gBStop est une variable booléene pour stopper l'exécution des threads. Voici le code de ma procédure Check_New_Item() Code :
Code :
La liste se remplit bien avec des articles n'existant pas sur le site. Problème : Lorsque j'augmente le nbre de threads à 5, j'ai plusieurs types d'erreurs non bloquantes: 1°) De temps à autres une fenetre "mécanisme de sécurité" s'affiche disant que plusieurs utilisateurs tentent de modifier le même enregistrement ARTICLE ( je suppose lorsque je veux mettre Done à "ok") Comment éviter ce cas de figure? 2°) il semblerait que lorsqu'il trouve pas un article sur le site en l'ajoutant, il ajoute également d'autres articles qui existent bien sur le site! (ce qui n'arrive jamais avec un seul thread) J'ai bien sûr essayer tous les modes d'exécution de threads (threadNormal,threadContexteGlobal,threadUtiliseHyperFile) sans succès! Merci d'avance à ceux qui pourrait m'aguiller sur ce coup |
||||
|
|
00
|
|
|
#2 |
|
Expert Confirmé
![]() Responsable de service informatique Inscription : janvier 2009 Messages : 1 545 ![]() |
Salut Zouzoukha,
Je vois déjà un problème dans ton code: les 5 threads traitent les mêmes articles, puisqu'ils partent avec 1 id de différence, et qu'ensuite ils balayent le fichier article "avec un pas de 1", et dans le même sens. Por ma part voilà ce que je ferai: 1. je lancerai les threads avec l'option ThreadNormal, pour copier le context lors du lancement. 2. dans chaque thread, je lirai les articles dans l'ordre, en tentant de les bloquer (option hBlocageLectureEcriture) Si la lecture réussi, l'enregistrement est bloqué et je peux le traiter. Sinon un autre thread l'a déjà bloqué, dans ce cas je passe au suivant. En quelque sorte je mets en place une "course" entre les threads, le premier à lire un enregistrement le traite. Il faut peut-être aussi mettre la partie du code qui crée NOUVEL_ARTICLE dans une section critique, à voir. Tatayo. |
|
|
00
|
|
|
#3 |
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Salut et merci Tatayo!
Effectivement j'avais commencé par le blocage en écriture et cela fonctionnait apparemment... Le seul hic était que j'avais beaucoup de fenêtres intempestives avec compteur 10 secondes disant que l'enregistrement a été bloqué par un autre utilisateur! Y a t-il un moyen de désactiver ce message? Merci d'avance... |
|
|
00
|
|
|
#4 |
|
Expert Confirmé
![]() Responsable de service informatique Inscription : janvier 2009 Messages : 1 545 ![]() |
(réponse à prendre avec des pincettes galactiques, je n'utilise pas les ordres h*)
Il me semble que ce message n'apparait que si tu ne testes pas le retour de hlit*. Ou alors il faut utiliser hSurErreur, je ne sais plus. Tatayo |
|
|
00
|
|
|
#5 |
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Salut Tatayo!
+1 Pour HsurErreur ![]() Je n'ai plus le message de blocage, mais je remarque que lorsqu'il y a blocage j'ai toujours le souci (à savoir qu'il m'ajoute un article aléatoire c'est terrible, je me demande s'il ne vaut pas mieux partager le fichier en autant de threads à lire? Ainsi chaque thread utilisera son propre fichier? Cela semble lourd, mais si je peux arriver à un résultat pourquoi pas? Merci encore |
|
|
00
|
|
|
#6 |
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Salut !!!
Merci à Tatayo qui m'a permis d'avancer un petit peu ![]() Récapitulatif : Après avoir crée manuellement des threads "attaquant" chacun un fichier HF, je me rends compte que j'ai toujours le même problème cela m'a donc permis de voir que le problème se situait au moment ou j'enregistre dans un fichier hyperfile l'article non trouvé! En passant en mode debug, j'ai remarqué qu'à l'instant t lorsque le thread1 doit enregistrer un article A1, au même moment chacun des articles en cours sur les autres threads sont enregistrés! A croire que les threads s'executent en parralèle mais lorsqu'un des threads doit accéder à un fichier HF, tous les autres y accèdent immédiatement! Fameux Contexte ? Vais je être obligé de créer autant de fichiers d'enregistrement utilisé par les threads que le nombre de threads? (j'espère que non ...)Merci d'avance! |
|
|
00
|
|
|
#7 |
|
Expert Confirmé
![]() Responsable de service informatique Inscription : janvier 2009 Messages : 1 545 ![]() |
Et si tu crées un alias sur le fichier en question dans chaque thread, est-ce que tu as encore le problème ?
Tatayo |
|
|
00
|
|
|
#8 | ||
|
Membre confirmé
![]() Développeur informatique Inscription : mars 2009 Messages : 92 ![]() |
Bonjour,
J'ai ne personnellement jamais réussi à faire fonctionner les contextes multiples avec les threads, ce en essayant toutes les options proposée par Windev. Le problème typique qui se présente est :
Pour palier ce problème, j'utilise systématiquement les requête SQL dans les threads, qui ne pose jamais de problème elles. (si on attribue bien l'identifiant !) Dans votre cas, je verrais bien quelque chose du genre : Code :
|
||
|
|
00
|
|
|
#9 |
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Salut Themayu et merci pour l'intérêt!
Cett instruction semble poser un problème : Code :
SdArticle est source de donnée = DonneIdentifiant() Code :
Un élément de type 'entier' ne peut pas être converti vers le type 'source de données'.
|
|
|
00
|
|
|
#10 | ||
|
Membre confirmé
![]() Développeur informatique Inscription : mars 2009 Messages : 92 ![]() |
Bonjour
L'identifiant doit donc attendre une chaîne (pas windev pour vérifier), vous pouvez essayer avec : Code :
Une discussion à ce sujet. |
||
|
|
00
|
|
|
#11 |
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Salut!
Encore moi! Que je crée des alias ou des fichiers physiques différents pour chaque thread, au moment ou un thread enregistre dans son fichier un enregistrement tous les autres fichiers des autres threads se retrouvent également avec des enregistrements aléatoires! Je commence à saturer ![]() ![]() Edit : Désolé Themayu, je viens de voir ta réponse en retard! Je reprends donc de l'autre coté Merci |
|
|
00
|
|
|
#12 |
|
Expert Confirmé
![]() Responsable de service informatique Inscription : janvier 2009 Messages : 1 545 ![]() |
Bonsoir,
Est-ce que le problème se pose aussi si les mises à jours sont faites avec des ordres SqlExec ? Tatayo. |
|
|
00
|
|
|
#13 |
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Salut Tatayo.
J'ai essayé le code de Themayu en effectuant une requête sql et en parcourant les résultats de cette requête, j'ai utilisé des requête sql de modif et d'ajout (update et insert) : J'ai toujours le même souci dès que j'utilise plus d'un thread! Avec un seul thread ca fonctionne à la perfection! C'est maintenant que je commence à appréhender les difficultés ce fameux "contexte" hyperfile |
|
|
00
|
|
|
#14 |
|
Expert Confirmé
![]() Responsable de service informatique Inscription : janvier 2009 Messages : 1 545 ![]() |
Je pense que le problème vient du fait qu'aucun test n'est fait pour s'assurer qu'un article n'est traité qu'une seule fois, par un seul thread.
Je vois peut-être une solution: 1. Il te faut une procédure globale, avec une section critique. Le but de cette procédure est de renvoyer à chaque appel l'id suivant dans le fichier article. La section critique permet d'être sur de n'avoir qu'un seul appel à un instant donné. Comme les variables statiques n'existent pas, on peut imaginer que l'ID du dernier article traité est mémorisé dans une variable globale. 2. Dans les threads, tu appelles cette procédure. Ensuite tu traites l'article en question avec le code de themayu (sans la boucle, évidemment). Si aucun id n'est renvoyé => fin du thread. Ainsi on est assuré qu'un article n'est traité que par un thread. Tatayo. |
|
|
00
|
|
|
#15 | ||||
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Salut!
Tatayo, t'as vraiment de la chance de pas être une fille ![]() T'aurais eu un de ces smacks pour la section critique!Tout fonctionne à merveille! Je met le code de la procédure globale qui empêche un article d'être lu par plusieurs threads! Code :
Code :
Merci en tout cas je n'ai plus de faux résultats |
||||
|
|
00
|
|
|
#16 | ||||
|
Expert Confirmé
![]() Responsable de service informatique Inscription : janvier 2009 Messages : 1 545 ![]() |
En fait tel qu'est écrite ta procédure, tu ne peux avoir qu'un seul thread qui traite un article. Donc tu ne profites pas du multi-thread.
Pour que ça marche, la procédure get_id doit se contenter de rechercher un id à traiter, et à le renvoyer. La variable globale n'est là que pour mémoriser l'Id en question entre chaque appel. On peut aussi imaginer un objet global, avec une méthode qui renvoe l'Id et un membre privé qui mémorise le dernier renvoyé. La recherche doit être dans une section critique. Par exemple: Code :
Code :
Tatayo. |
||||
|
|
00
|
|
|
#17 | ||
|
Membre confirmé
![]() Développeur informatique Inscription : mars 2009 Messages : 92 ![]() |
Bonsoir,
Pour votre problème de rapidité, c'est peut être due au placement du SectionCritiqueFin : Code :
|
||
|
|
00
|
|
|
#18 |
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Salut!
@Tatayo, désolé, je n'y arrive pas avec les fonctions sqlexec... J'ai donc essayé avec les requêtes Hexecuterequetesql() mais toujours pareil au niveau des perfs (1 thread = 5 threads en terme de vitesse) @Themayu Effectivement j'avais testé en mettant sectioncritiquefin avant le renvoyer, mais j'obtenais des doublons comme auparavant (je suppose qu'il renvoyait la même valeur à tous les threads) C'est en placant renvoyer avant la fin section critique que cela fonctionnait! merci encore pour l'aide... J'avais été vite en besogne en mettant résolu |
|
|
00
|
|
|
#19 |
|
Membre chevronné
![]() Inscription : avril 2008 Messages : 723 ![]() |
Salut et désolé de remonter le post
Malgré mon multi-thread, je suis à la même vitesse qu'avec un thread! J'ai comme un goulot d'étranglement au niveau de GET_ID Une autre petite idée? merci d'avance |
|
|
00
|
Copyright © 2000-2013 - www.developpez.com