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

Langage Delphi Discussion :

Problème de fermeture d'une fiche modale


Sujet :

Langage Delphi

  1. #1
    Membre averti Avatar de Moez.B
    Homme Profil pro
    Développeur Delphi
    Inscrit en
    Mars 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2006
    Messages : 219
    Points : 370
    Points
    370
    Par défaut Problème de fermeture d'une fiche modale
    Bonjour,
    J'ai un petit problème avec la fermeture d'une fiche modale depuis un Thread : En faite la fiche modale n'est qu'une petite fenêtre affichant une jauge de progression, tant que mon traitement n'est pas encore fini , la jauge est entrain d'avancer. Une fois fini , je dois fermer cette fiche modale.
    J'ai prévu une petite procédure qui intercepte le message :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure HandleModalOk(var Msg : TMessage); message WM_USER + 1;
    Rien de spécial dans cette procédure car elle passe mon ModalResult à mrOk
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    procedure TFGauge.HandleModalOk(var Msg: TMessage);
    Begin
      ModalResult := mrOK;
    End;
    A la fin de mon traitement sur le thread j'envoie le message suivant avec un SendMessage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SendMessage(FGauge.Handle, WM_USER+1, 0, 0);
    sachant que FGauge est passé comme paramètre du constructeur de mon Thread au constructeur de ma classe métier.
    En déboguant, le SendMessage fait bien son boulot en passant dans mon HandleModalOk et mon ModalResult est à mrOk MAIS ma fenêtre n'est pas fermée. j'ai essayé avec le PostMessage , puis le Perform mais toujours pas d'impact sur la fermeture de ma fiche.
    J'ai posé un TButton sur la fenêtre de progression avec un ModalResult est à mrOk , je clique : la fenêtre se ferme ( comportement normal ) , dans HandleModalOk : je lance le Click du Bouton mais la fenêtre de se ferme pas .
    J'ai l'impression que le message est bien envoyé mais il n'est pas interprété puisque la commande : ModalResult := mrOk n'a aucun impact aussi.
    Ma question est : comment obliger la fermeture de cette fenêtre modale à la fin de traitement ?
    Merci d'avance
    "L'homme supérieur est celui qui a une bienveillance égale pour tous, et qui est sans égoïsme et sans partialité." [Confucius]
    "Celui qui n'évolue pas disparaît." [Charles Darwin]
    “Without requirements or design, programming is the art of adding bugs to an empty text file.” [Louis Srygley]

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 449
    Points : 24 856
    Points
    24 856
    Par défaut
    Pourquoi faire aussi compliquer ?

    Utilise OnTerminate, qui appel la fermeture de la fenêtre de progression !
    D'ailleurs OnTerminate est appelé via Synchronize (c'est le TThread qui le fait en interne) donc aucun soucis pour utiliser la VCL

    Citation Envoyé par Aide Delphi
    Remarque: La méthode affectée à l'événement OnTerminate est exécutée dans le contexte du thread principal au lieu du contexte du thread qui vient de se terminer. Cela signifie que vous pouvez accéder à l'interface utilisateur de votre application en toute sécurité sans appeler la méthode Synchronize
    As-tu essayé tout simplement d'utiliser Close() dans le gestionnaire de WMUser ?
    Active les DCU de debug, tu pourras voir l'intérieur de la boucle modale, c'est peut-être un bug ! quelle version ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre averti Avatar de Moez.B
    Homme Profil pro
    Développeur Delphi
    Inscrit en
    Mars 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2006
    Messages : 219
    Points : 370
    Points
    370
    Par défaut
    Salut,
    En faite , j'ai un thread que je lui passe la fiche de progress comme paramètre dans le constructeur, ensuite je repasse la fiche comme paramètre dans l'appel de ma méthode métier.
    J'instancie et je fais le kill de mon thread manuellement. le OnTerminate ne résout pas mon problème car la fiche de progression est passée en paramètre.
    J'ai tenté de faire simple en supprimant l'appel au thread et en appelant directement la méthode de ma classe métier comme suit
    Le pile d'appel est comme suit : une fenêtre de progression --> appel de la méthode de la classe métier (en lui passant la fiche de progression en Self ) --> Traitement métier --> Fin du traitement ( faire un SendMessage )
    J'ai essayé de changer en Close() mon gestionnaire de message , j'ai simulé aussi le click sur le bouton dont le ModalResult est mrOk mais en vain.
    Je suis passé dans le debug des Dcu , ça passe dans tout le cycle de fermeture de la fiche sans pour autant la fermer.
    La version du Delphi est XE.
    Merci.
    "L'homme supérieur est celui qui a une bienveillance égale pour tous, et qui est sans égoïsme et sans partialité." [Confucius]
    "Celui qui n'évolue pas disparaît." [Charles Darwin]
    “Without requirements or design, programming is the art of adding bugs to an empty text file.” [Louis Srygley]

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 449
    Points : 24 856
    Points
    24 856
    Par défaut
    Citation Envoyé par Moez.B Voir le message
    Le pile d'appel est comme suit : une fenêtre de progression --> appel de la méthode de la classe métier (en lui passant la fiche de progression en Self ) --> Traitement métier --> Fin du traitement ( faire un SendMessage )
    C'est ce qui me choque le plus en fait !
    Ce n'est pas une bonne séparation IHM / Métier, il faut privilégié un couplage faible entre les classes, passez l'IHM à l'objet métier, pas bon du tout ça !

    Ce qui aurait été élégant c'est de faire un évènement OnProgress dans l'objet métier
    L'appelant lui est libre de fournir un gestionnaire qui effectue la progression

    Ton OnProgress fourni un Position Max, le 0 / 100 c'est au début, puis le 100 / 00 en fin du Execute
    tu peux même inclure un paramètre de retour AAbort pour gérer un bouton d'arrêt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     TProgressEvent = procedure(Sender: TObject; APosition: Integer; ACount: Integer; var Aborted: Boolean) of object;
    De plus, Est-ce que le thread est bien utile, si tu lance un traitement bloquant, en gros tu vas simuler une pseudo progression (je le fais pour des gros SQL)
    Par contre, si c'est des boucles, le thread n'a pas d'intérêt puis qu'en modale, ton utilisateur doit attendre

    l'intérêt du thread, c'est soit de permettre à l'utilisateur de faire autre chose pendant que cela travaille
    ou alors d'éviter qu'une application affiche 'Ne Répond pas' lors d'un long traitement insécable

    Un sujet proche : Ecran d'attente chargement
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 688
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 688
    Points : 13 117
    Points
    13 117
    Par défaut
    La pile de messages ne se vide pas. L'animation de la barre de progression ne serait pas une boucle sans fin par hasard ?

  6. #6
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    ça ressemble à une fenêtre qui n'est pas modale en fait...ModalResult c'est juste une variable dont la valeur est testée dans ShowModal pour savoir quand il faut sortir de la boucle. En dehors d'un appel à ShowModal elle n'a aucune fonction....notamment elle ne ferme pas la fenêtre.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 449
    Points : 24 856
    Points
    24 856
    Par défaut
    Citation Envoyé par Moez.B Voir le message
    Je suis passé dans le debug des Dcu , ça passe dans tout le cycle de fermeture de la fiche sans pour autant la fermer.
    Tu n'aurais pas un gestionnaire de OnClose qui n'affecte pas caHide mais plutôt caNone et donc ne fait pas la fermeture ?
    De plus comme ta fenêtre est modale, tu as surement le Free juste après comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Patience := TPatience.Create();
    try
      ObjetMetier.LancerTraitementAsynchrone(Patience);
      Patience.ShowModal();
    finally
      Patience.Free();
    end;
    Ou ce que je proposais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Patience := TPatience.Create();
    try
      Patience.Show();
      ObjetMetier.OnProgress := ProgressEventHandler;
      LancerTraitementBloquant();
    finally
      Patience.Free();
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  8. #8
    Membre averti Avatar de Moez.B
    Homme Profil pro
    Développeur Delphi
    Inscrit en
    Mars 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2006
    Messages : 219
    Points : 370
    Points
    370
    Par défaut
    Bonjour,
    Merci pour toutes vos réponses.
    La fiche de progression était au début un champs de la classe métier et était lancée avec un simple Show();
    Le traitement est en lui même dans un thread car il est :
    - Long ( gros requêtes SQL )
    - Bloquant à des niveaux ( requêtes HTTP bloquantes GET, PUT, POST , DELETE ) utilisant des sockets bloquants.
    J'ai réussi à résoudre les problèmes de genre : "Application de répond pas .." et les Freezes que génère le traitement. Mais, il reste ce point de la fiche de progression : elle doit être en modale et c'est pourquoi j'ai eu recours à un ShowModal au lieu d'un Show. De cette façon, l'utilisateur ne peut pas appeler le traitement une fois tant que le premier n'est pas fini sinon je vais avoir face à de mauvaises surprises après
    Le ShowModal bloque toutes les actions sur les composants de la fiche ( notamment la Progress Form et mes labels d'informations ) et il attend un ModalResult et c'est pour cela que je fais appel à mon gestionnaire de message personnalisé à la fin du traitement pour lui dire : Tout est Ok : ton Modalresult est un mrOk donc la fiche doit se libérer ( ce qui n'est pas le cas ) , pendant ce temps là si le traitement n'est pas encore fini , je peux agir sur les composants de la fiche en faisant les Steps et mettant à jour mes Labels.
    Donc, mon but c'est de : apporter un comportement modale à une fiche qui n'est pas sensée être modale pour ne pas laisser la main à l'utilisateur de faire n'importe quoi pendant mon traitement.
    J'ai trouvé une autre façon de le faire en regardant le fonctionnement de ShowModal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    TObjetGenerique.ActivateAccessToOtherForms();  // Méthode pour rendre les autres fiches en Disabled
    ObjetMetier := TObjetMetier.Create(); // Ici, je crée la fiche de  progression , et je fais son Show tout court au lieu de ShowModal
    try
      ObjetMetier.LaunchTraitement();
    Finally
      KillObject(ObjetMetier);
      DesactivateAccessToOtherForms(); // Méthode pour remettre les autres fiches en Enabled et restaurer le Focus sur la fiche appelante du traitement
    End;
    Dans la première méthode, ActivateAccessToOtherForms : j'ai ce bout de code piqué de ShowModal de CustomForms où je peux désactiver les fiches de l'application et sauvegarder la dernière fiche active
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class procedure TObjetGenerique.ActivateAccessToOtherForms();
    Begin
      FWindowList   := DisableTaskWindows(0);
      FActiveWindow := GetActiveWindow;
    End;
    Dans la seconde méthode, DesactivateAccessToOtherForms : je réactive le tout et je restaure a fiche appelante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    procedure TObjetGenerique.ActivateAccessToOtherForms();
    Begin
      EnableTaskWindows(FWindowList);
      if (FActiveWindow <> 0) and IsWindow(FActiveWindow) then
        SetActiveWindow(FActiveWindow);
    End;
    Avec ce mécanisme, j'ai pu avoir ma fiche de progression en modale sans que l'utilisateur puisse faire quoique soit pendant le traitement et attendre calmement la fin de l'exécution
    "L'homme supérieur est celui qui a une bienveillance égale pour tous, et qui est sans égoïsme et sans partialité." [Confucius]
    "Celui qui n'évolue pas disparaît." [Charles Darwin]
    “Without requirements or design, programming is the art of adding bugs to an empty text file.” [Louis Srygley]

  9. #9
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 688
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 688
    Points : 13 117
    Points
    13 117
    Par défaut
    J'ai juste fait un essai de fermeture d'un fiche modale depuis un thread secondaire suivant ton exemple (ModalResult suite à la réception d'un message) et ça fonctionne très bien.

    Tu as clairement quelque chose qui empêche le vidage de la pile de messages. SendMessage(WM_USER +1) ne passe pas par la pile et en debug te semble fonctionner correctement mais ce n'est pas le cas des messages post-és (WM_DESTROY etc.).

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 449
    Points : 24 856
    Points
    24 856
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    La pile de messages ne se vide pas. L'animation de la barre de progression ne serait pas une boucle sans fin par hasard ?
    Dans une application de StressTest d'une autre application, j'ai une boucle qui simule des traitements, quelques ProcessMessages
    Comme le dit AndNotOr, même si l'on fait un Close de la fenêtre, celle-ci ne se ferme pas parce que la boucle tourne

    Comment simules-tu ta barre de progression si tes requêtes sont bloquantes, tu en lances plusieurs à la suite ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  11. #11
    Membre averti Avatar de Moez.B
    Homme Profil pro
    Développeur Delphi
    Inscrit en
    Mars 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2006
    Messages : 219
    Points : 370
    Points
    370
    Par défaut
    Salut,
    En faite, la jauge de progression est une présentation des étapes de traitement. Exemple : j'ai un traitement qui se compose de 7 parties séparées : la progress d'avance à chaque fin de partie. J'ai aussi un partie qui détaille dans une jauge secondaire qui permet d'aller un peu plus dans le détail : Exemple : j'ai un appel GET pour le WebService machin : j'attends le retour : je fais signe , j'ai récupéré le retour XML : je fais signe , j'analyse le retour : je fais signe , je mets à jour ma base je fais signe ... etc ..
    Pour les requêtes SQL assez lourdes : Des Insert Into Select de masse : j'avance la jauge pendant chaque étape aussi : Création de la requête en dynamique : j'avance , phase du Post , j'avance , phase du Commit de la transaction j'avance ..
    etc ..
    Pour mes appels WebServices , je n'ai pas utilisé les composant Indy (IdHttp) mais les composants Synapse (HttpSend), j'ai pu résoudre les Freeze potentiels pour les gros appels (notamment des GET sur des catalogues de produits etc ..) en ajoutant une petite classe de CallBack qui ne fait qu'un Application.ProcessMessages dans une class pocedure : j'ai trouvé une petit évènement dans la classe Sock de THttpSend : j'ai fait de sorte à ce que :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
          HTTP_GET.Sock.HeartbeatRate := 250;
          HTTP_GET.Sock.OnHeartbeat   := TCallBack.Heartbeat;
    ça simule à peu près ce que fait le composant IdAntiFreeze pour les composants Indy pour gérer les cas de figures du Freeze sur les appels HTTP ou SMTP.
    Revenant au cas du SendMessage , je passe dans le Debug et je passe même à la fin du code du ShowModal dans TCustomForm dans Forms , mais la fenêtre ne se ferme pas ( même si je passe par un Hide ce qui est assez surpenant tout de même car Action est caHide dans le OnClose ).
    "L'homme supérieur est celui qui a une bienveillance égale pour tous, et qui est sans égoïsme et sans partialité." [Confucius]
    "Celui qui n'évolue pas disparaît." [Charles Darwin]
    “Without requirements or design, programming is the art of adding bugs to an empty text file.” [Louis Srygley]

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 449
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 449
    Points : 24 856
    Points
    24 856
    Par défaut
    Selon la doc le OnHeartbeat doit boucler pour récupérer les données paquet par paquet, lorsque le délai est dépassé, il fait signe, et continue
    Avec le OnHeartbeat et vu que tu utilises Application.ProcessMessages, je suppose que le thread ne concerne pas cette partie

    Le thread c'est pour les SQL ?
    Comme tu fais signe entre le thread secondaire et le thread principal de la VCL ?

    Pense que le Hide, lui même passe par du Perform
    Et si cela traite pas les messages ...
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  13. #13
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 688
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 688
    Points : 13 117
    Points
    13 117
    Par défaut
    Citation Envoyé par Moez.B Voir le message
    j'ai pu résoudre les Freeze potentiels pour les gros appels (notamment des GET sur des catalogues de produits etc ..) en ajoutant une petite classe de CallBack qui ne fait qu'un Application.ProcessMessages
    Ce qui tend à prouver que ces appels se font depuis la tâche principale et non la secondaire.
    Je ne crois pas que ton programme s'exécute comme tu le penses. Je commencerais par contrôler cela.

    Nomme tes threads :
    Dans le Create de la fiche principale ajoute TThread.NameThreadForDebugging('Principale');. Dans Execute du thread (pas dans Create), ajoute NameThreadForDebugging(ClassName);. Place des points d'arrêt dans tes différentes procédures et une fois dessus, affiche la liste des threads dans l'EDI (menu Voir -> Fenêtres de debugage -> Threads ou Ctrl+Alt+T). Le sigle "Lecture" sera affiché sur la tâche en cours lors de l'arrêt.

  14. #14
    Membre averti Avatar de Moez.B
    Homme Profil pro
    Développeur Delphi
    Inscrit en
    Mars 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2006
    Messages : 219
    Points : 370
    Points
    370
    Par défaut
    Salut ,
    Bien évidement , le OnHeartBeat c'est une affaire en dehors du Thread 'métier'
    En faite la méthode métier est appelé dans le Execute du Thread : Donc , je crée mon thread 'métier' secondaire , je fais le Override de son Execute ( en appelant le traitement ) et dans ce traitement là , je crée ma fiche de progression qui s'occupe d'avancer la jauge pour chaque étape de traitement. La destruction de mon Thread est manuelle ( pas avec un FreeOnTerminate à True ).
    Donc la suite de mon code est : Création du thread --> dans le Create j'appelle le Execute --> Dans l'Execute j'appele mon traitement métier --> Je crée la jauge de progression et j'avance à chaque étape --> à la fin du traitement je fais le Kill de ma jauge --> je reviens à la fiche du premier point d'appel ( Create du Thread ) et je fais son Free.
    Il est vrai que la directive de mettre tout le traitement dans un Thread n'a pas de sens dans ce contexte de traitement synchrone et bloquant que ce soit du côté des appels HTTP ou bien requêtes SQL.
    Merci.
    "L'homme supérieur est celui qui a une bienveillance égale pour tous, et qui est sans égoïsme et sans partialité." [Confucius]
    "Celui qui n'évolue pas disparaît." [Charles Darwin]
    “Without requirements or design, programming is the art of adding bugs to an empty text file.” [Louis Srygley]

  15. #15
    Membre averti Avatar de Moez.B
    Homme Profil pro
    Développeur Delphi
    Inscrit en
    Mars 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2006
    Messages : 219
    Points : 370
    Points
    370
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Ce qui tend à prouver que ces appels se font depuis la tâche principale et non la secondaire.
    Je ne crois pas que ton programme s'exécute comme tu le penses. Je commencerais par contrôler cela.

    Nomme tes threads :
    Dans le Create de la fiche principale ajoute TThread.NameThreadForDebugging('Principale');. Dans Execute du thread (pas dans Create), ajoute NameThreadForDebugging(ClassName);. Place des points d'arrêt dans tes différentes procédures et une fois dessus, affiche la liste des threads dans l'EDI (menu Voir -> Fenêtres de debugage -> Threads ou Ctrl+Alt+T). Le sigle "Lecture" sera affiché sur la tâche en cours lors de l'arrêt.
    J'ai fait comme tu as dit : c'est étrange, le traitement passe dans le thread principal de mon application pourtant je l'ai mis dans un Thread à part et je l'ai passé dans son Execute.
    "L'homme supérieur est celui qui a une bienveillance égale pour tous, et qui est sans égoïsme et sans partialité." [Confucius]
    "Celui qui n'évolue pas disparaît." [Charles Darwin]
    “Without requirements or design, programming is the art of adding bugs to an empty text file.” [Louis Srygley]

  16. #16
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 688
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 688
    Points : 13 117
    Points
    13 117
    Par défaut
    Citation Envoyé par Moez.B Voir le message
    ... --> dans le Create j'appelle le Execute --> ...


    Si tu fais cela, tu lances la procédure Execute depuis la tâche principale... Tu ne dois pas appeler Execute, JAMAIS !

  17. #17
    Membre averti Avatar de Moez.B
    Homme Profil pro
    Développeur Delphi
    Inscrit en
    Mars 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2006
    Messages : 219
    Points : 370
    Points
    370
    Par défaut
    Je fais le resume() dans le Create alors pour séparer mon traitement dans le thread secondaire déjà créé ?
    "L'homme supérieur est celui qui a une bienveillance égale pour tous, et qui est sans égoïsme et sans partialité." [Confucius]
    "Celui qui n'évolue pas disparaît." [Charles Darwin]
    “Without requirements or design, programming is the art of adding bugs to an empty text file.” [Louis Srygley]

  18. #18
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 688
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 688
    Points : 13 117
    Points
    13 117
    Par défaut
    Dans le constructeur du TThread, le thread proprement dit est toujours créé dans l'état suspendu, quelque soit le paramètre. Le démarrage se fait plus tard dans la méthode AfterConstruction. On peut donc y initialiser tout ce qu'on veut sans risque. Créer un TThread en spécifiant CreateSuspended à TRUE (qui signifie en fait garder le thread tel-quel : en attente) est nécessaire uniquement si on veut faire de l'initialisation après MyThread := TThread.Create(TRUE);.

    Il faut bien comprendre que TThread n'est qu'un objet Delphi facilitant la gestion d'un thread "Windows". Ce n'est pas LE thread.

    Maintenant, il manque un peu de code pour en dire plus...

  19. #19
    Membre averti Avatar de Moez.B
    Homme Profil pro
    Développeur Delphi
    Inscrit en
    Mars 2006
    Messages
    219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Développeur Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2006
    Messages : 219
    Points : 370
    Points
    370
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Au moment où tu es dans le constructeur du TThread, le thread proprement dit est créé dans l'état suspendu, on peut donc initialiser tout ce qu'on veut sans risque. Créer un TThread en spécifiant l'état suspendu est nécessaire uniquement si on veut faire de l'initialisation après MyThread := TThread.Create(TRUE);. Il faut bien comprendre que TThread n'est qu'un objet Delphi facilitant la gestion d'un thread "Windows". Ce n'est pas LE thread.

    Maintenant, il manque un peu de code pour en dire plus...
    Salut
    J'ai déjà créé des threads avec des états suspendus à False , je passe mes paramètres correctement dans le constructeur et j'implémente mon traitement dans le Execute.
    Le problème dans mon problème initial de la fiche de progression modale, l'envoi de mon message WM_USER+1 n'a aucun impact sur la fermeture de la fiche et c'est pour cela que j'ai tenté un appel de l'Execute directement dans le Create du Thread. Maintenant que j'ai pu résoudre ce petit problème de 'Modal' , je peux me mettre à tête reposée pour corriger plein d'autres Threads qui sont lancées de cette façon ( Un Execute dans le Create ) pour isoler leur traitement dans un thread secondaire alors qu'ils sont encore dans le Thread principal
    Merci
    "L'homme supérieur est celui qui a une bienveillance égale pour tous, et qui est sans égoïsme et sans partialité." [Confucius]
    "Celui qui n'évolue pas disparaît." [Charles Darwin]
    “Without requirements or design, programming is the art of adding bugs to an empty text file.” [Louis Srygley]

  20. #20
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par Moez.B Voir le message
    Salut ,
    Bien évidement , le OnHeartBeat c'est une affaire en dehors du Thread 'métier'
    En faite la méthode métier est appelé dans le Execute du Thread : Donc , je crée mon thread 'métier' secondaire , je fais le Override de son Execute ( en appelant le traitement ) et dans ce traitement là , je crée ma fiche de progression qui s'occupe d'avancer la jauge pour chaque étape de traitement. La destruction de mon Thread est manuelle ( pas avec un FreeOnTerminate à True ).
    Donc la suite de mon code est : Création du thread --> dans le Create j'appelle le Execute --> Dans l'Execute j'appele mon traitement métier --> Je crée la jauge de progression et j'avance à chaque étape --> à la fin du traitement je fais le Kill de ma jauge --> je reviens à la fiche du premier point d'appel ( Create du Thread ) et je fais son Free.
    Il est vrai que la directive de mettre tout le traitement dans un Thread n'a pas de sens dans ce contexte de traitement synchrone et bloquant que ce soit du côté des appels HTTP ou bien requêtes SQL.
    Merci.
    est-ce à dire que tu crées la fiche depuis le Thread ? tout le code VCL doit être exécuté impérativement dans le Thread Principal, il n'y a pas dérogation.

    l'usage d'une fenêtre modale et d'un Thread est expliqué ici

    dans cet exemple, j'utilise directement l'API CreatThread mais un TThread ferait très bien l'affaire. Pour mettre à jour la progressBar, il FAUT passer un un Synchronize (si tu utilises TThread) ou un Send/PosMesssage. Généralement je passe par le PostMessage

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    begin
      PostMessage(Handle, WM_USER + 1, Pos, Max);
    end
     
    procedure TWait.WMUser1(var Msg: TMessage);
    begin
      ProgressBar.Max := Msg.LParam;
      ProgressBar.Position := Msg.WParam;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Fermeture d'une Fiche avec animation
    Par touhami dans le forum Langage
    Réponses: 2
    Dernier message: 28/04/2006, 19h43
  2. ouverture/fermeture d'une fenêtre modale showModelessDialog
    Par marti dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 04/01/2006, 05h03
  3. Réponses: 9
    Dernier message: 08/11/2005, 09h56
  4. Comment interdire la fermeture d'une fiche empilée ?
    Par psau dans le forum C++Builder
    Réponses: 3
    Dernier message: 05/07/2004, 14h01
  5. probléme d'affichage d'une fiche
    Par sb dans le forum Composants VCL
    Réponses: 7
    Dernier message: 29/08/2002, 09h43

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