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

Bases de données Delphi Discussion :

JvUIB et Thread


Sujet :

Bases de données Delphi

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut JvUIB et Thread
    Salut à tous.

    Dans une application Delphi7 de reprise de données (passer des données d'un système d'information X vers un autre - le nôtre) j'utilise une base de données Firebird 2 avec les composants UIB.

    Je lance certaines procédures stockées via des threads. Pendant leurs éxécution, j'affiche une fenetre d'attente. A la fin de la procédure, la fenetre disparait et rend la main au soft.

    Le problème, c'est que parfois, le thread ne me rend pas la main. et donc le fenetre d'attente s'affiche en permenance. Seul solution : tuer la tache ! Pas bon !

    Avant j'utilisai Firebird 1 + IBX, je n'ai jamais eu le problème. Etant novice avec les UIB, il y a peut être des choses à faire ou à ne pas faire.

    Merci pour vos réponses.
    @+, Alex

  2. #2
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut,

    alors, vraiment, ca n'intéresse personne ?

    @+, Alex

  3. #3
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    donne au moins le code de la procedure Execute de thréad
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut,

    Voici le code de la méthode Execute :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
      inherited;
     
      try
        try
          TJvUIBQuery(FParametres).ExecSQL;
          TJvUIBQuery(FParametres).Tag := 1;
        except
          TJvUIBQuery(FParametres).Tag := 0;
        end;
      finally
        Terminate;
      end;
    La propriété "Tag" me sert à savoir si la méthode est sortie en erreur ou pas.

    Merci de ta solicitude.
    @+, Alex

  5. #5
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Salut
    Citation Envoyé par alexvdb Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
          TJvUIBQuery(FParametres).ExecSQL;
    Je ne saisi pas très bien, c'est un transtypage ?

    sinon, avec les compos UIB il est préférable d'utiliser la méthode Execute plutôt qu'ExecSQL.

    A tester.

    @+ Claudius

  6. #6
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    et cette inherited; sére à quoi
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut,

    1. TJvUIBQuery(FParametres) => oui c'est un transtypage. En fait, j'ai dérivé la classe TThread pour pouvoir y ajouter ma fameuse fenetre d'attente ! En plus, j'ai ajouté dans le constructeur un parametre de type "Pointer" me permettant de transmettre une série de paramètres. Dans le cas présent, j'envoie comme paramètre à mon thread directement une instance de TJvUIBQuery.

    2. OK, c'est noté pour la méthode Execute. Je teste ca ce matin ... en arrivant au taf ! Mais au fait, que fait "Execute" que ne fait pas "ExecSQL" (ou inversement) ?

    3. inherited => parce j'ai déjà surchargé la méthode "Execute" de la classe TThread (cf 1). Donc ...

    @+, Alex

  8. #8
    Membre confirmé Avatar de TryExceptEnd
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Sexe : Homme

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 501
    Points : 574
    Points
    574
    Par défaut
    Citation Envoyé par alexvdb Voir le message
    Je lance certaines procédures stockées via des threads. Pendant leurs éxécution, j'affiche une fenetre d'attente. A la fin de la procédure, la fenetre disparait et rend la main au soft.
    A quoi sert le thread si tu fait attendre l'utilisateur ?
    Si vous êtes libre, choisissez le Logiciel Libre.

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut,

    Les threads me servent à lancer des procédures stockées longues. Pendant qu'elles s'éxécutent, une fenetre d'attente dit gentiment aux utilisateurs de patientez quelques instants (un peu comme les hots lines) pour ne pas qu'ils s'impatientent et écrasent de leurs gros doigts boudinés les 3 touches que sont CTRL+ALT+SUPPR pour tuer la tâche (ce qui par ailleurs pourraient éventuellement mettre à mal la base de données ...).

    Enfin, moi, à leur place, une mise à jour de base qui bloquent/frisent l'appli. pendant 5 longues minutes, ca m'énerverait ...

    @+, Alex

  10. #10
    Membre confirmé Avatar de TryExceptEnd
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Sexe : Homme

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 501
    Points : 574
    Points
    574
    Par défaut
    Si tu met en service un thread, normalement c'est pour rendre la main a l'utilisateur sans attente.
    Sinon, pour utiliser une procedure stockée avec UIB, voici la méthode :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    JvUIBQuery.BuildStoredProc('NOM_Procedure_Stockee');
    JvUIBQuery.Params.ByNameAsString['Parametre_Entree'] := 'Valeur';//éventuellement.
    JvUIBQuery.Open;
    Var_String:=JvUIBQuery.Fields.ByNameAsString['Parametre_Sortie'];//éventuellement.
    JvUIBQuery.Close(etmCommit);
    Si vous êtes libre, choisissez le Logiciel Libre.

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut,

    Ok, merci, je sais comment on lance une procédure stockée avec JvUIB ... mais, sérieux, je tiens absolument à mettre cette foutu fenetre d'attente pendant le longue procédure stockée. Le fait que tu ne comprennes pas pourquoi m'est égal ...

    Maintenant, si quelqu'un a d'autre propositions, je suis preneur.

    @+, Alex

  12. #12
    Membre confirmé Avatar de TryExceptEnd
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2006
    Messages
    501
    Détails du profil
    Informations personnelles :
    Sexe : Homme

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 501
    Points : 574
    Points
    574
    Par défaut
    Désolé de ne pouvoir te comprendre.
    Si vous êtes libre, choisissez le Logiciel Libre.

  13. #13
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut,

    Le problème n'est pas de comprendre ou pas. Le problème est que si l'appli reste bloqué trop longtemps, les utilisateurs vont tuer la tâche violemment avec toutes les conséquences que cela implique. D'où l'utilisation des thread !

    En fait, l'appli que je développe consiste à faire passer des données issues d'une base de données sql, ou de fichiers texte ou binaires, qu'il me faut décoder en ensuite importer dans ma base Firebird. Ces données doivent être traités dans un ordre précis. De plus pour adapter ces données à la structure de la base Firebird, j'ai besoin dans certains cas d'importer ces données dans des tables de "travail" et ensuite de les re-traiter via une procédure stockée. Suivant le volume des données, cette procédure stockée peut prendre +/- de temps. Pendant ce laps de temps, j'ai besoin de signaler à l'utilisateur que l'appli n'est pas planté mais qu'elle travaille bel et bien, et en même temps, je ne veux pas que l'utilisateur lance un autre traitement ! D'ou l'utilite de la fenetre d'attente ...

    @+, Alex

  14. #14
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut

    Alors, les fêtes de noël ne vous ont pas inspirés pour mon problème ? toujours pas ?

    @+, Alex

  15. #15
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 458
    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 458
    Points : 24 871
    Points
    24 871
    Par défaut
    Citation Envoyé par alexvdb Voir le message
    Salut,

    3. inherited => parce j'ai déjà surchargé la méthode "Execute" de la classe TThread (cf 1). Donc ...
    , normalement, on ne fait pas inherited sur une méthode ancêtre abstraite, si on y accède via des références de classes donc sans que le compilateur puisse savoir quoi sera lancer avant, cela déclenche une EAbstractError, dans l'utilisation simple du TThread le inherited est éliminé par le compilateur...
    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

  16. #16
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut,

    Dans mon cas, je n'ai pas ce soucis parce que j'ai dérivé 2 fois la classe TThread :

    TThread -> TAttente = class(TThread) -> TThreadRequete = class(TAttente)

    Ce qui explique le "inherited".

    Merci de t'intéresser de mon problème.
    @+, Alex

  17. #17
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 458
    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 458
    Points : 24 871
    Points
    24 871
    Par défaut
    Que fait alors le Execute de TAttente ? rien je suppose puisque le but est de lancer ExecSQL ...

    J'ai fait exactement la même chose, certains requêtes très longue sous MySQL faisait que l'application apparaissait toute blanche, et dès que tu apprends à l'utlisateur le CTRL+ALT+SUPP, il l'utilise comme un bourrin, j'ai donc aussi fait un Thread, ... avec un joli bouton annuler (optionnel) pour killer la session (j'ai une connexion dans le thread principal, et une autre dans le thread secondaire, cela permet d'arrêter la requête longue sans nuire à la connexion principale, en MySQL, il y a la commande KILL N°Session, pratique !)

    C'est tout de même très problématique d'avoir une différence de comportement entre deux bibliothèques différentes, tes objets entre le thread VCL et le thread secondaire sont-ils bien isolés ? pas de Application.ProcessMessages hasardeux dans le thread pouvant provoquer un DeadLock ?
    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

  18. #18
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut,

    En fait, TAttente.Execute se charge en gros de 3 choses :

    - Appeler une méthode protected du genre DoExecute (qu'il bien entendu surcharger ...)
    - De gérer les éventuelles éxceptions
    D'appeler la méthode Terminate en fin de thread ou en cas d'exception

    Voici le code de TAttente.Execute :

    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
     
    try
      LancerExecution;
    except
      on E:Exception
      begin
        with FMessage do
        begin
          Message := 'Une erreur est survcenue durant l''éxécution d''un ou plusieurs thread(s).' +
                          #13#10#13#10'Message de l''application : ' + E.Message +
                          #13#10#13#10'Classe : ' + Self.ClassName;
          TypeMessage := mtError;
          Boutons := [mbOk];
        end;
        Synchronize(AfficherMessageSync);
      end;
      Terminate;
    end;
    Puis dans la méthode LancerExecution se trouve l'appel à TJVUIBQuery.Execute. Le fenêtre d'attente est en fait affichée par le thread principale et le thread secondaire se contente d'éxécuter la requete ou la procédure stockée.

    Je n'avais pas pensé à l'isolation de la requete dans une transaction différente (je pense qu'une connection pour le thread est un peu exégéré ...). Je vais voir pour éxécuter cela dans un transaction unique !

    @+, Alex

  19. #19
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 458
    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 458
    Points : 24 871
    Points
    24 871
    Par défaut
    Mais tu fais

    TThreadRequete.Execute, il lance donc TAttente.Execute via le inherited, mais que fait donc LancerExecution ? afficher la fenêtre, mais ensuite, il quitte la fonction pour continuer TThreadRequete.Execute et lancer le SQL, il y a une drôle de construction, j'espère que DoExecute encapsule un OnExecute, mais surtout pas appelant le Execute lui même, ... je ne comprends pas ton utilisation du thread (je n'ai je crois jamais hérité deux fois)

    Sinon les exceptions sont attaprées dans la ThreadProc qui encaspule le Execute, et il faut utiliser FatalException dans OnTerminate (qui est appelé bien sur en Synchronize) pour savoir si il y a une exception, ... d'ailleurs Terminate() ne faut que changer la valeur de Terminated, c'est inutile donc de le lancer, puisque tu n'as même pas de boucle ... et que le thread se termine par nature puisqu'il sort de la méthode Execute ...
    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

  20. #20
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2002
    Messages : 33
    Points : 8
    Points
    8
    Par défaut
    Salut,

    Effectivement TAttente.LancerExecution ne fait absolument rien ! Fût un temps où la méthode était même déclarée en abstract, mais ca planté. Jamais essayer de trouver pourquoi ...

    Par contre, non, la fenetre est affiché par le thread principal qui attend la fin de l'éxécution du thread secondaire.

    Pourquoi dériver deux fois : parce que TAttente possède des méthodes et propriétés propre à la mise à jour de la fenetre d'attente du thread principal. De cette facon, tous mes thread qui demande cette fonctionnalité de fenetre d'attente en dispose même s'ils n'en tirent pas parti.

    Merci, je ne connaissais pas la propriété FatalException. Et j'avoue ne mettre jamais intéressé à la facon de TThread lancait les méthodes à "threader" via le pointeur ThreadProc. Je pense qu'il y a moyen de mieux faire ma classe TAttente, moins barbare ...

    Je modifie tout ca et te tiens au courant ! Merci pour ton aide !
    @+, Alex

Discussions similaires

  1. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 09h00
  2. récupérer la valeur de sortie d'un thread
    Par jakouz dans le forum Langage
    Réponses: 3
    Dernier message: 31/07/2002, 11h28
  3. Programmer des threads
    Par haypo dans le forum C
    Réponses: 6
    Dernier message: 02/07/2002, 13h53
  4. Réponses: 5
    Dernier message: 12/06/2002, 15h12
  5. [Kylix] Pb de Thread !!
    Par Anonymous dans le forum EDI
    Réponses: 1
    Dernier message: 25/04/2002, 13h53

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