IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

WinDev Discussion :

Impossible d'arrêter un thread


Sujet :

WinDev

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2008
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 256
    Points : 85
    Points
    85
    Par défaut Impossible d'arrêter un thread
    Bonjour à tous !

    Là, il y a quelque chose qui m'échappe. J’exécute la fonction ThreadExécute() avec tout ce qui va bien dedans ... jusque là pas de problème, le code s’exécute correctement en revanche lorsque je demande au thread de s'arrêter via la fonction ThreadArrête() il ne se passe rien je reste bloqué sur la fonction malgré lui avoir donné un temps.

    Ça marché très bien avant et plus maintenant, j'ai redémarré le PC etc et rien n'y fait.

    Avez-vous une idée ou solution à mon problème ?

    Merci d'avance à tous.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    J'ai eu moi aussi affaire à la gestion des threads un peu spéciale de PC soft.

    Déjà, il faudrait que je saches : que fais-tu comme traitements dans ton thread?
    Si tu fais des requêtes ou des accès fichier sur une BDD et que cette requête prend un peu de temps, alors ça ne m'étonne pas que tu n'arrives pas à arrêter ton thread.

    En effet, il suffit qu'une fonction wlangage prenne beaucoup de temps (et non pas une procédure utilisateur, nuance!) et ça peut en effet empêcher l'arrêt d'un thread.

    L'astuce dans ce cas consiste à appeler un autre thread dans le thread et d'attendre la fin du "sous-thread" à partir du thread appelant, de la manière suivante dans la fonction du Thread:

    Code wlangage : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    ThreadExécute(sMonThread,threadNormal,proFAppelTraitementAsynchrone)
    TANTQUE ThreadEtat(sMonThread)<>threadInexistant alors
       ThreadPause(50)
    FIN

    Ainsi, le thread principal n'est pas bloqué si tu essaies de l'arrêter. Seul le sous-thread continuera de tourner mais tant pis pour lui!

    Chose intéressante : dans la version 19, PC soft a rajouté une fonction "ThreadFin" pour forcer l'arrêt du thread... Comme quoi, il y avait vraiment un problème dans leur gestion des threads!
    [EDIT] Ah je viens de voir dans la doc de PC soft qu'en fait la fonction "ThreadFin" c'est ni plus ni moins que ThreadArrête("")... Leur gestion des threads est une vraie calamité...
    Dernière modification par Invité ; 11/12/2013 à 10h24.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Août 2008
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 256
    Points : 85
    Points
    85
    Par défaut
    Bonjour Ph_Gr,

    Tout d'abord merci de ton aide et de ta réponse, je me sers du thread pour exécuter du code w-langage dans la récupération de fichiers sur un serveur FTP.

    Cela m'évite de bloquer mon appli pendant le téléchargement, à la fin de celui-ci je souhaite afficher un message à l'utilisateur pour lui demander d'installer ou non la MAJ mais ça ne fonctionne pas car je suis bloqué par la tentative d'arrêt du thread.

    J'utilise FTPConnect() avant le thread et si c'est Ok, je fais un FTPRécupère() à la fin du téléchargement qui peu durée plusieurs minutes selon le débit utilisateur, je fais un FTPDéconnecte() et ensuite un ThreadArrete().

    A titre d'information :
    J'ai mis en commentaire la section de téléchargement (c'est trop long d'attendre à chaque qu'il est fini de télécharger pour avoir le ThreadArrête().
    J'arrive donc instantanément sur l'arrêt du Thread qui ne fonctionne toujours pas !

    Effectivement la gestion des Threads à l'air d'être une vraie calamité !!!

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Citation Envoyé par Jb_One73 Voir le message
    je me sers du thread pour exécuter du code w-langage dans la récupération de fichiers sur un serveur FTP.

    Cela m'évite de bloquer mon appli pendant le téléchargement, à la fin de celui-ci je souhaite afficher un message à l'utilisateur pour lui demander d'installer ou non la MAJ mais ça ne fonctionne pas car je suis bloqué par la tentative d'arrêt du thread.
    Oui, c'est logique, c'est tout à fait le contexte pour lequel il faut utiliser des threads normalement.

    Citation Envoyé par Jb_One73 Voir le message
    J'utilise FTPConnect() avant le thread et si c'est Ok, je fais un FTPRécupère() à la fin du téléchargement qui peu durée plusieurs minutes selon le débit utilisateur, je fais un FTPDéconnecte() et ensuite un ThreadArrete().

    A titre d'information :
    J'ai mis en commentaire la section de téléchargement (c'est trop long d'attendre à chaque qu'il est fini de télécharger pour avoir le ThreadArrête().
    J'arrive donc instantanément sur l'arrêt du Thread qui ne fonctionne toujours pas !
    C'est bizarre, j'aurais dit qu'en fait c'est la fonction "FTPRécupère" qui prend du temps et qui empêche le thread de s'arrêter. C'est la seule chose qui peut l'empêcher de s'arrêter. Normalement, le thread s'arrête dès qu'il sort de la fonction dans le thread, s'il a passé le ftpdéconnecte, il n'est absolument plus nécessaire d'arrêter le thread.

    Les symptômes d'un thread qui ne s'arrête pas sont normalement :
    - La fonction "threadetat(sNomThread)" renvoie autre chose que "ThreadInexistant" (où "sNomThread" est le nom du Thread)
    - L'appel à "ThreadArrête" bloque complètement

    si tu n'as pas ces 2 symptômes, c'est que ton thread est déjà arrêté. As-tu vérifié tout cela?
    Peux-tu me montrer un peu de code pour voir comment tu t'y prends?

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Août 2008
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 256
    Points : 85
    Points
    85
    Par défaut
    Pour répondre à tes 2 questions :
    - J'ai bien utilisé la fonction ThreadEtat qui me dit que mon Thread est bien existant.
    - Le bloquage se fait sur la fonction ThreadArrête(), en mode débogage je n'arrive pas à passer au traitement suivant.

    Je me suis dit, tant pis je ne supprime pas le thread (je met rien) mais impossible d'afficher une boite de dialogue si le thread n'est pas détruit, en revanche une fenêtre système appeler avec la fonction Info() fonctionne correctement.

    A y perdre son latin !!! Thread et Windev ne fait pas bon ménage

  6. #6
    Invité
    Invité(e)
    Par défaut
    Peux-tu me montrer un bout de code pour que je vois?

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Août 2008
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 256
    Points : 85
    Points
    85
    Par défaut
    Début de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // Tentative de connexion
    Pg_JbiUpdate.gnIDConnexionFTP = FTPConnecte(Pg_JbiUpdate.gsServeur, Pg_JbiUpdate.gsUtilisateur, Pg_JbiUpdate.gsMotDePasse, Pg_JbiUpdate.gsPort)
     
    SI Pg_JbiUpdate.gnIDConnexionFTP <> -1 ALORS
     
    	// La mise à jour s'effectue en tâche de fond
    	ThreadExécute("TH1",threadNormal,Pl_LiveUpdate)
     
    	// On attend que le thread se soit lancé
    	ThreadAttendSignal()
     
    SINON
    	Erreur("Impossible de se connecter au serveur FTP")
    	FinProgramme()
    FIN
    Code la procédure du Thread
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    // Résumé : <indiquez ici ce que fait la procédure>
    // Syntaxe :
    // Pl_LiveUpdate ()
    //
    // Paramètres :
    //	Aucun
    // Valeur de retour :
    // 	Aucune
    //
    // Exemple :
    // Indiquez ici un exemple d'utilisation.
    //
    PROCEDURE Pl_LiveUpdate()
     
    // On indique que le thread s'est chargé et lancé
    ThreadEnvoieSignal(".")
     
    // Contrôle du nombre de thread à un instant t grâce aux sémaphores
    SémaphoreDébut("SEM_LIMITE")
     
    // Création du répertoire Temp
    fRepCrée(ComplèteRep(fRepExe) + "Temp")
     
    // On récupère le fichier contenant le n° de la dernière version MAJ sur le serveur FTP
    SI FTPRécupère(Pg_JbiUpdate.gnIDConnexionFTP,"/****/"+gsNomLogicielMAJ+"/Version.txt",ComplèteRep(fRepExe) + "Temp") = Faux ALORS ThreadArrête("TH1"); RETOUR
     
    // Lecture du fichier contenant le n° de la version de l'exe
    nIDFichier 	est un entier
    sChaîneLue 	est une chaîne
     
    // Ouverture du fichier
    nIDFichier = fOuvre(ComplèteRep(fRepExe) + "Temp\Version.txt", foLecture)
     
    SI nIDFichier <> -1 ALORS
     
    	// Lecture du fichier
    	sChaîneLue = fLitLigne(nIDFichier)
     
    	// Compare la version de l'exe
    	SI ExtraitChaîne(sChaîneLue,rangDernier,"=",DepuisFin) <> ExeInfo(exeVersion) ALORS
     
    		// Affiche le plan de téléchargement
    		FEN_UPDATE..Plan = 2
     
    		// date et heure de démarrage
    		sHeureDépartUpload = DateHeureSys()
     
    		// Récupère la mise à jour du logiciel
    		//FTPRécupère(Pg_JbiUpdate.gnIDConnexionFTP,"/****/****/",ComplèteRep(fRepExe) + "Temp",Progression)
     
    	SINON
    		Info("Il n'y a actuellement aucune mise à jour de disponible.")
    	FIN
     
    	// Fermeture du fichier
    	fFerme(nIDFichier)
     
    SINON
    	Erreur()
    FIN		
     
    // Déconnexion
    FTPDéconnecte(Pg_JbiUpdate.gnIDConnexionFTP)
     
    // On peut libérer une unité du sémaphore
    SémaphoreFin("SEM_LIMITE",1)
     
    // Arrêt du thread
    SI ThreadEtat("TH1")<>threadInexistant ALORS
    	SI ThreadArrête("TH1",200) = Faux ALORS
    		// On vérifie qu'il existe toujours
    		SI ThreadEtat("TH1")<>threadInexistant ALORS
    			Erreur(ChaîneConstruit("Impossible d'arrêter le thread n° : %1","TH1"))
    		FIN
    	FIN
    FIN
     
    // Affichage du message de fin de téléchargement
    gbOkMsgInstalle = Vrai
    ExécuteTraitement(BTN_Msg,trtClic)
    J'ai remplacé certaines indications par des *** pour des raisons de confidentialité.

  8. #8
    Invité
    Invité(e)
    Par défaut
    Merci.

    Alors, c'est bien ce que je pensais, en fait tu n'as pas bien compris à quel moment un thread se termine réellement.

    Il faut vraiment que tu prennes conscience que ton thread "TH1" c'est ni plus ni moins que toute la procédure "Pl_LiveUpdate". Autrement dit, tu peux toujours demander un "threadetat" sur ton thread "TH1" à l'intérieur de la procédure "Pl_LiveUpdate", ça te renverra forcément tout le temps "threadEnCours" puisque tu es dedans.

    Ce qu'il faudrait que tu fasses c'est lancer un premier thread, puis dans ce thread tu lances un autre thread qui lui va faire le traitement ftp. Le 1er thread pourra faire un "ThreadAttend" du 2ème et éventuellement le tuer en cas de besoin.

    D'autre part, je te conseille d'éviter de faire appel à des fonctions d'IHM dans des threads autres que le thread principal, normalement ce n'est pas fait pour. PC SOFT indique d'ailleurs dans sa doc qu'il ne faut pas appeler des fonctions IHM bloquantes telles que "Erreur()" ou "Info()" par exemple, mais moi je conseille aussi de ne pas manipuler d'éléments d'IHM car normalement tous les éléments d'IHM sont censé être dans un environnement dit "cloisonné". Je trouve d'ailleurs que WinDev est trop permissif là-dessus. Manipuler des éléments d'IHM dans des threads secondaires peut entrainer des effets parfois bizarre, j'en ai d'ailleurs déjà fait l'expérience.

    Dans le Framework.NET, tout cela est beaucoup plus clair, et depuis le Framework.ET 4.5 l'utilisation des tâches est beaucoup plus simple qu'avant. PC Soft aurait dû aussi faire un peu de ménage dans leur système à ce sujet, mais, comme d'habitude, ils sont en retard!... et la gestion des threads avec WinDev reste extrêmement compliquée!

    Pour simplifier au début, tu pourrais peut être lancer le 1er thread en procédure automatique qui se lance en thread, et tu créée à partir de là le second thread qui fait le traitement et qui est attendu par le 1er thread.

    Dis-moi si tu as besoin que je précise certaines choses. Après je n'ai pas trop le temps de rentrer dans tous les détails vu que je travaille en même temps...
    Dernière modification par Invité ; 11/12/2013 à 16h13.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Août 2008
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 256
    Points : 85
    Points
    85
    Par défaut
    Bonjour Ph_Gr,

    Ok ! Merci pour ta réponse, pourrais-tu me fournir un exemple de code ?
    Je ne vois pas trop ce qu'il faut faire ... 1er thread, 2ème thread.

    Je te remercie d'avance.

  10. #10
    Invité
    Invité(e)
    Par défaut
    OK, je vais te fournir un petit exemple avec une connexion http à Google dont je veux récupérer le résultat HTML... Après ce sera à toi de l'adapter pour ta connexion FTP.

    Avant tout, il faut que tu consulte l'aide de la fonction "ThreadMode", et que tu l'appelles une bonne fois pour toute au démarrage de ton projet. Cette fonction sert à choisir quelle politique tu veux appliquer pour les threads. Par défaut, les threads sont en section critique automatique (ça tu voudras peut-être le modifier) et tous les processeurs possibles sont utilisés (ça c'est une option qu'il faut garder).

    Ensuite, voici l'exemple.
    Quelquepart, je déclare le nom de mon thread, dans mon exemple ce sera dans une constante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    CONSTANT
    	CST_NOM_THREAD_CONNEXION="ThreadConnexion"
    FIN
    Etant donné qu'il est impossible pour une fonction s'exécutant dans un thread secondaire de renvoyer un résultat, je vais devoir créer une variable globale pour récupérer le résultat HTML (ça c'est un gros problème sous WinDev, c'est tellement plus simple avec DotNet!)

    Maintenant, à partir d'un bouton de test, j'appelle une fonction en lui disant que c'est sous mon thread :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //Test
    ThreadExécute(CST_NOM_THREAD_CONNEXION,threadNormal,RécupèreHTMLRésultat,"http://www.google.fr")
    et il n'y a rien d'autre à faire ici.

    Code de RécupèreHTMLRésultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    PROCEDURE RécupèreHTMLRésultat(LOCAL sURL est une chaîne)
    sNomSousThread est une chaîne = "ThreadRécupèreHTMLRésultat" //Nom de mon sous-thread
     
    //J'initialise ma variable globale.
    gsRésultatHTMLTmp = ""
     
    //A faire éventuellement ici : griser des boutons, etc...
     
    ThreadExécute(sNomSousThread,threadNormal,RécupèreHTMLRésultatAsync,sURL)
    TANTQUE ThreadEtat(sNomSousThread)<>threadInexistant
    	ThreadPause(10) //Cela mettra le thread actuel en pause. Pendant ce temps, le thread actuel sera rapidement facile à stopper.
    FIN
     
    //A faire éventuellement ici : dégriser des boutons, etc...
    Ce code lance donc le fameux "sous-thread" qui va vraiment faire le traitement. D'ailleurs, voici le contenu de la procédure "RécupèreHTMLRésultatAsync" qui s'exécute dans le sous-thread :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    PROCEDURE RécupèreHTMLRésultatAsync(LOCAL sURL est une chaîne)
    //Je vais récupérer le résultat dans la variable globale :
    SI HTTPRequête(sURL) ALORS
    	gsRésultatHTMLTmp = HTTPDonneRésultat()
    FIN
     
    //Je trace le résultat.
    Trace(gsRésultatHTMLTmp)
     
    //On peut ensuite envisager ici de mettre le résultat dans un contrôle HTML par exemple. Pas recommandé mais plus simple, sinon très compliqué...
    Quel est l'intérêt de faire ainsi un sous-thread? Eh bien si on avait fait appel directement à httprequête et httpdonnerésultat dans le thread "ThreadConnexion", si l'une des fonctions "httprequête" ou "httpdonnerésultat" prend énormément de temps, alors on n'aurait pas pu arrêter rapidement le thread "ThreadConnexion" avec la fonction "ThreadArrete". J'ai eu surtout ce problème plutôt avec des "hExecuteRequete", "hExecuteRequeteSQL".
    Dans mon cas, si je fais "ThreadArrete" sur "ThreadConnexion", le thread s'arrête tout de suite. Certes, le sous-thread tourne toujours mais tant pis pour lui!

    Alors j'ai abordé ce problème assez rapidement, car il faudrait aussi prendre en considération l'attribution dynamique d'un nom de sous-thread quand on arrête brutalement un thread, et il y a aussi le problème de l'ouverture d'une fenêtre à partir d'un thread secondaire...

    Enfin, bref... Les threads sous WinDev, c'est très compliqué!

    Voilà, j'espère que ça répond à tes questions...

  11. #11
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mars 2002
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Mars 2002
    Messages : 899
    Points : 1 103
    Points
    1 103
    Par défaut
    Je n'ai pas tout à fait la même vision des choses.

    Le problème d'arrêt des threads se passe toujours quand on tente de les arrêter à partir de la procédure appelante.
    En effet, le thread termine son instruction en cours avant de s'arrêter. Et dans le cas d'un FTPRécupère(), l'instruction en cours peut durer des heures...
    Une solution est de stopper le thread à partir de l'intérieur du thread lui même.
    Une simple variable globale fait l'affaire.

    Mon idée repose sur le fait que la procédure CallBack "ProgressionFTP" de mon exemple stoppe la récupération si elle renvoie Faux. A tester donc, mais je pense que c'est bien le cas.

    Je ne l'ai pas testé, donc il peut y avoir des erreurs, mais ça devrait ressembler à ça :
    Code déclarations globales : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    gbThreadActif est un booléen
    Code bouton de lancement thread : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    gbThreadActif = vrai
    ThreadExécute(sMonThread,threadNormal,proFAppelTraitementAsynchrone)
    Code proFAppelTraitementAsynchrone : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    PROCEDURE proFAppelTraitementAsynchrone()
    nIdCnx est un entier
    nIdCnx = FTPConnecte(...)
    SI PAS gbThreadActif alors RETOUR
    FTPRecupère(nIdCnx, "\MesFichiersSource\*", "D:\MonDossierDest\","ProgressionFTP")
    SI PAS gbThreadActif alors RETOUR
    FTPDeconnecte(nIdCnx)
    Code procedure ProgressionFTP : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    PROCEDURE ProgressionFTP(LOCAL nTaille est un entier, LOCAL nTailleTotale est un entier)
    //Procédure CallBack appelée automatiquement par FTPTransfère
    SI PAS gbThreadActif alors RENVOYER Faux    //Provoque l'arrêt de la récupération FTP, et donc la sortie du thread par la fonction "proFAppelTraitementAsynchrone"
    //Ici, instructions permettant de gérer une éventuelle jauge
    RENVOYER Vrai
    Code bouton d'arrêt du thread : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    gbThreadActif = Faux

  12. #12
    Invité
    Invité(e)
    Par défaut
    Bonjour Bowen,

    La question n'est pas d'avoir ou pas la même vision des choses, la question est qu'est-ce que l'on a expérimenté et est-ce cela fonctionne ou pas.

    J'ai passé des mois à tester les threads sous windev et je connais bien aussi le fonctionnement des tâches sous le Framework.Net.

    Tu mentionnes cependant un cas particulier où l'on bénéficie d'une procédure de callback pour un rapport de progression. Dans la plupart des cas (comme par exemple des hexecuterequete) on ne bénéficie pas d'un callback, donc l'appel de la fonction en question est bloquée dans le thread lors de l'appel, donc ce n'est pas possible déjà de faire un threadArrête dans le thread lui-même dans ces conditions.

    De plus, il n'y a vraiment que pc soft pour utiliser encore des threads à l'ancienne en permettant au thread en cours de se "suicider", car sur .NET dans la classe "Task" ce n'est plus possible, il faut gérer un système de jeton d'annulation et c'est beaucoup plus propre comme cela!

    D'autre part, dans ta façon de faire, lorsque le "ftprécupère" est bloqué et donc si le ftp ne progresse plus, Est-ce que la fonction de callback continue à être appelée à intervalles réguliers? Pas sûr...

  13. #13
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mars 2002
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Mars 2002
    Messages : 899
    Points : 1 103
    Points
    1 103
    Par défaut
    Je ne donne pas ça comme une solution miracle non, bien sûr.
    C'était comme je l'ai dit une autre vision des choses.
    Pour la remarque sur le HExecuteRequeteSQL, il y a aussi un moyen
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    HNbEnr(sdMaReq, HNonBloquant)    //Lance l’exécution réelle de la requête et la récupération des lignes
    TANTQUE PAS sdMaReq..ExecutionTerminée
        SI PAS gbThreadActif alors RETOUR
        Multitache(-1)
    FIN
    Mais encore une fois, c'est une simple vision des choses, une seconde piste.
    Ta solution est peut-être bien meilleure.

    J'ai aussi testé les Threads avec Windev, pour un programme gérant des appels par sockets (et donc des threads d'attente de messages entre mon appli sur serveur et mon PDA), et je me souviens d'avoir dû gérer l'arrêt de certains threads par "suicide" comme tu le dis.

  14. #14
    Invité
    Invité(e)
    Par défaut
    HNbEnr avec l'option HNonBloquant, j'avoue que je ne connaissais pas. Tu viens de m'apprendre quelque chose et je t'en remercie.

    Je pensais que tous les appels étaient bloquants et c'est vrai que je n'avais jamais pensé à regarder des options spécifiques de ce genre sur le fonction HNbEnr... En plus je ne m'attendais vraiment pas à trouver une telle option dans cette fonction, je l'aurais plutôt vue dans le hexecuterequete lui-même.

    Je vais te mettre un "pouce vert" pour m'avoir montré cela car ça pourrait peut-être m'aider dans beaucoup de cas...

    Après, c'est sûr que dès que l'on dispose d'une action non bloquante, cela change tout de suite la donne. Mais dans ce cas, au lieu de faire un "ThreadArrête" directement dans le thread, autant faire un retour, comme tu viens de le montrer dans ton exemple d'ailleurs.

  15. #15
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Mars 2002
    Messages
    899
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Mars 2002
    Messages : 899
    Points : 1 103
    Points
    1 103
    Par défaut
    Je ne place jamais un threadArrete dans le thread appelé (autokill par thread, ça plante pas ça ?).
    Il faut effectivement mieux faire sortir la procédure simplement.
    Avec une temporisation dans le bouton d'arrêt, du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    gbThreadActif = Faux
    TANTQUE threadEtat(sMonThread) <> threadInexistant
        Multitache(-10)
        //Prévoir ici un threadStop forçant le stop pour le cas où on le thread ne s'arrête vraiment pas au bout de plusieurs tours. Le fait de doubler les méthodes d'arrêt ne peut pas être nocif.
    FIN

  16. #16
    Invité
    Invité(e)
    Par défaut
    Ah dans ce cas j'ai dû mal comprendre ce que tu voulais dire au début et je m'en excuse. En fait on est bien d'accord.

    C'est quand j'ai vu cette citation

    Citation Envoyé par Bowen Voir le message
    ...Une solution est de stopper le thread à partir de l'intérieur du thread lui même...
    que j'en ai déduit que tu voulais faire "suicider" le thread.

    Mais en fait tu voulais dire que le mieux c'est de trouver une fonction non bloquante puis boucler pour voir s'il faut l'arrêter et là, dans ce cas, c'est vraiment l'idéal c'est sûr. Cela revient d'ailleurs justement à un équivalent de la solution du Framework .NET dans lequel il y a des jetons d'annulation.

    Mais le problème avec windev est qu'il n'y a pas toujours de cas où l'on dispose d'une fonction non bloquante.

    Cela dit, le coup du hnbEnr ça m'a vraiment beaucoup aidé et je t'en remercie encore! Si je l'avais su avant, il y a beaucoup de choses que j'aurais fait autrement!
    Dernière modification par Invité ; 13/12/2013 à 15h39.

  17. #17
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Bowen Voir le message
    Pour la remarque sur le HExecuteRequeteSQL, il y a aussi un moyen
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    HNbEnr(sdMaReq, HNonBloquant)    //Lance l’exécution réelle de la requête et la récupération des lignes
    TANTQUE PAS sdMaReq..ExecutionTerminée
        SI PAS gbThreadActif alors RETOUR
        Multitache(-1)
    FIN
    Après avoir creusé ce sujet intéressant, j'ai découvert, après expérimentations, qu'il n'était pas nécessaire de faire appel à hnbenr avec hnonbloquant pour "lancer" la requête. En fait la seule boucle "TANTQUE PAS sdMaReq..ExecutionTerminée" suffit! Cela veut dire qu'en fait l'exécution des requêtes se passe toujours d'une manière asynchrone sur le poste client et c'est lorsque l'on fait appel à une instruction telle que "hnbenr" ou "hlitpremier" ou "pour tout" que le blocage a lieu.
    Mais tout ça ce n'était pas très bien mis en évidence dans la doc de PC soft et c'est bien dommage!

  18. #18
    Membre régulier
    Profil pro
    Inscrit en
    Août 2008
    Messages
    256
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 256
    Points : 85
    Points
    85
    Par défaut
    Bonjour à tous !

    Je tenais tout à d'abord à vous remercier pour votre aide, j'ai trouvé une autre méthode pour détruire le thread sans avoir besoin de créer un sous-thread (enfin du moins différemment).

    J'ai créé une procédure locale que j'ai appelé ScruteFinFTP ou j'ai utilisé le Timer Automatique.

    Je le démarre à la fin de l'initialisation de la fenêtre, je l'ai réglé à 1s et à l'infini. Ensuite dans mon code de traitement qui me permet de récupérer mes fichiers sur mon serveur FTP j'ai créé une variable globale que je met à vrai une fois la procédure terminé.

    Le thread qui Scrute la fin de ma procédure execute ThreadArrete() si la variable globale est à vrai.

    C'est la même méthode que Ph_Gr mais un peu plus faignant !

    Tes conseils m'ont été précieux puisqu'ils m'ont permis de mieux comprendre le principe de fonctionnement des Threads, je viens de recevoir la nouvelle de Windev 19 et ThreadFin je ne vois pas la différence avec ThreadArrete (redondance ???)

    Bonne journée à tous !

  19. #19
    Invité
    Invité(e)
    Par défaut
    Bonjour jb,
    Citation Envoyé par Jb_One73 Voir le message
    ...C'est la même méthode que Ph_Gr mais un peu plus faignant !
    La méthode de Bowen est vraiment plus propre si tu as accès à une callback avec la fonction de ftp...

    Citation Envoyé par Jb_One73 Voir le message
    ...faignant...
    En fait, ça s'écrit "fainéant". Et à la base l'origine du mot désigne vraiment le fait de "faire du néant" donc "fait néant" donc "fainéant".

    Citation Envoyé par Jb_One73 Voir le message
    ...je viens de recevoir la nouvelle de Windev 19 et ThreadFin je ne vois pas la différence avec ThreadArrete (redondance ???)
    Comme je te disais (enfin il me semble l'avoir dit) il n'y a pas de différence. C'est la même chose que "ThreadArrête" mais sans paramètres.
    Voir ici pour les détails.

    A+

Discussions similaires

  1. Arrêter un thread en python ?
    Par fanou31 dans le forum Général Python
    Réponses: 7
    Dernier message: 23/06/2013, 18h15
  2. Réponses: 2
    Dernier message: 05/10/2006, 17h56
  3. [Thread] arrêter un thread
    Par melvar dans le forum Concurrence et multi-thread
    Réponses: 4
    Dernier message: 10/04/2006, 18h06
  4. Réponses: 18
    Dernier message: 06/04/2005, 14h09
  5. Arrêter une Thread brutalement!
    Par Rodrigue dans le forum C++Builder
    Réponses: 2
    Dernier message: 18/01/2004, 21h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo