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 :

thread et WaitForMultipleObjects


Sujet :

Langage Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    291
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 291
    Points : 144
    Points
    144
    Par défaut thread et WaitForMultipleObjects
    Bonjour

    Je n'arrive pas à utiliser la fonction WaitForMultipleObjects.

    Dans ma fiche principale j'ai ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        for ms := 1 to 12 do
        begin
          tab_thread[ms-1]:=TThreadGraphSynthese.Create(tab_ibc_qry[ms-1],nom_stored_proc,prjt,'T'+IntToStr(t),EncodeDate(an,ms,1),IncMonth(EncodeDate(an,ms,1),1));
          //recupere le handle
          tab_thread_hdl[ms-1]:=tab_thread[ms-1].Handle;
        end;
     
        //attend la fin des threads
        WaitForMultipleObjects(12,@tab_thread_hdl,TRUE,INFINITE);
    Je créé les threads récupere le handle et attend la fin

    Voici la fonction de création de mon 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
     
    constructor TThreadGraphSynthese.Create(ibc_qry:TIBCQuery; 
    nom_stored_proc,prjt,trbn: string; dt_deb,dt_fin:TDateTime);
    begin
      //FreeOnTerminate:=TRUE;
      IbcQry:=ibc_qry;
      IbcQry.SQL.Text:='SELECT * FROM '+nom_stored_proc+'(:PRJT, :TRBN, 
    :DATE_DEB, :DATE_FIN)';
      IbcQry.ParamByName('PRJT').AsString:=prjt;
      IbcQry.ParamByName('TRBN').AsString:=trbn;
      IbcQry.ParamByName('DATE_DEB').AsDate:=dt_deb;
      IbcQry.ParamByName('DATE_FIN').AsDate:=dt_fin;
      ThreadTerminated:=FALSE;
      OnTerminate:=OnTerminateProcedure;
      Inherited Create(FALSE);
    end;
     
    procedure TThreadGraphSynthese.OnTerminateProcedure(Sender: TObject);
    begin
      ThreadTerminated:=TRUE;
    end;
    procedure TThreadGraphSynthese.Execute;
    begin
      IbcQry.Execute;
    end;
    je remarque que lorsque la fonction WaitForMultipleObjects est terminée mes
    threads ne le sont pas car si je regarde la variable ThreadTerminated elle
    est à false. Et ensuite j'ai des violations d'acces sur des variables non
    initialisées.

    Merci

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 753
    Points : 13 337
    Points
    13 337
    Par défaut
    Commence déjà par mettre le inherited à la première ligne du constructor.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    constructor TThreadGraphSynthese.Create(ibc_qry:TIBCQuery; 
    nom_stored_proc,prjt,trbn: string; dt_deb,dt_fin:TDateTime);
    begin
      Inherited Create(FALSE);
      ...
    end;

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    291
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 291
    Points : 144
    Points
    144
    Par défaut
    Bonjour,

    C'est fait. Le comportement du waitformultipleobjects est le meme

    Merci

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 753
    Points : 13 337
    Points
    13 337
    Par défaut
    Il n'y a rien d'autre qui me choque . WaitForMultipleObjects est correct !
    Je viens encore de faire un essai et ça fonctionne...

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    291
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 291
    Points : 144
    Points
    144
    Par défaut
    Ca fonctionne?

    Et bien ca alors!! Je veux bien voir le code car il doit y avoir quelque chose de different. Moi quand Waitfor... est terminé mon boolean ThreadTerminated est à false

    Amitiés

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 753
    Points : 13 337
    Points
    13 337
    Par défaut
    Je n'avais pas regardé ton code en entier...

    OnTerminate devrait pointer sur une méthode du thread principal et non sur une du thread secondaire. (L'appel étant Synchronize)

    Dans ton cas, il suffirait aussi simplement de mettre ThreadTerminated:=TRUE à la fin du Execute.

  7. #7
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Juste une remarque :
    Est-ce que tu es sûr que le composant TIBCQuery soit thread-safe ? et surtout est-ce que tu utilises une connexion Db par query ou est-ce que tu as une seule connexion pour toutes les query ?

    Je dis ça parce que je connais très peu d'API base de données qui acceptent d'exécuter des requêtes concurrantes avec la même connexion... et encore celles qui le font sérialisent les requêtes.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    291
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 291
    Points : 144
    Points
    144
    Par défaut
    Bonsoir,

    Est-ce que tu es sûr que le composant TIBCQuery soit thread-safe ? et surtout est-ce que tu utilises une connexion Db par query ou est-ce que tu as une seule connexion pour toutes les query ?
    J'ai fait le test en créant une variable locale dans le execute et en l'incrémentant. J'ai enlevé tout ce qui concerne les ibquery.
    while cpt<200
    inc(cpt)

    Le probleme est le meme.

    J'ai trouvé ceci : http://www.delphicorner.f9.co.uk/articles/op4.htm
    The first thing you'll notice in the code is that I actually employ two types of threads. One, TMasterThr, is used to spawn the other two threads. That's pretty much all it does. Why did I do that? I wanted to include a WaitForMultipleObjects call in my code which would make the program wait for the copying threads to terminate before moving on. But the calling thread just doesn't wait; it sleeps, which means that it doesn't receive any messages while it's waiting. Therefore, if I put the WaitForMultipleObjects call in the main thread of the program, it would lock up and not receive messages. Not good.
    Apparement on ne peut pas l'utiliser dans la fiche principale. Mais pour quelle raison? Je ne vois pas trop

    Amitiés

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 560
    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 560
    Points : 25 156
    Points
    25 156
    Par défaut
    au fait à quoi sert ThreadTerminated ? la propriété Terminated du TThread ne suffit pas ?

    Sinon, WaitForMultipleObjects c'est un peu violent, pour le confort de l'utilisateur, tu pourrais faire une boucle et afficher une pseudo progression*, car là, tu auras droit à un écran gelé ...

    A la fin du Execute, chaque thread va augmenter un compteur (géré avec section critique) et lorsqu'il arrive au nombre de thread, c'est que c'est terminé, en plus cela peut simuler cette pseudo progression et sans freeze !

    Pour IBQuery, il est recommandé, d'instancier l'objet Connection et Query dans le Thread ... un ancien collègue avait eu des problèmes en utilisant des objets qui interagisse entre les threads ...

    Sinon, ton SQL à quoi ressemble-t-il, par hazard, ça ne pourrait pas se lancer en une seule requête avec des Group by bien utilisé ?

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    291
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 291
    Points : 144
    Points
    144
    Par défaut
    Bonjour,

    au fait à quoi sert ThreadTerminated ? la propriété Terminated du TThread ne suffit pas ?
    Sans doute. Je ne connaissais pas son existence

    Sinon, WaitForMultipleObjects c'est un peu violent, pour le confort de l'utilisateur, tu pourrais faire une boucle et afficher une pseudo progression*, car là, tu auras droit à un écran gelé ...
    Oui c'est ce que je fais déjà. Mais j'appelle application.processmessages pour rafraichir et ca me prend du cpu. Je voulais tester avec waitformul... qui parrait il est optimisée pour faire de l'attente

    A la fin du Execute, chaque thread va augmenter un compteur (géré avec section critique) et lorsqu'il arrive au nombre de thread, c'est que c'est terminé, en plus cela peut simuler cette pseudo progression et sans freeze !
    Je vais essayer ca

    Pour IBQuery, il est recommandé, d'instancier l'objet Connection et Query dans le Thread ... un ancien collègue avait eu des problèmes en utilisant des objets qui interagisse entre les threads ...
    Je créé une connexion un query par thread que je passe en argument par le create. Je peux les creer dans le thread mais j'en ai besoin apres que le thread soit terminé. Donc le thread ne doit pas les détruire. A voir...

    Sinon, ton SQL à quoi ressemble-t-il, par hazard, ça ne pourrait pas se lancer en une seule requête avec des Group by bien utilisé ?
    Euh je vais regarder car j'appelle pas mal de procédures

    Merci

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    12
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 12
    Points : 11
    Points
    11
    Par défaut
    Citation Envoyé par calou_33 Voir le message
    Bonjour,


    Sans doute. Je ne connaissais pas son existence


    Oui c'est ce que je fais déjà. Mais j'appelle application.processmessages pour rafraichir et ca me prend du cpu. Je voulais tester avec waitformul... qui parrait il est optimisée pour faire de l'attente


    Je vais essayer ca


    Je créé une connexion un query par thread que je passe en argument par le create. Je peux les creer dans le thread mais j'en ai besoin apres que le thread soit terminé. Donc le thread ne doit pas les détruire. A voir...


    Euh je vais regarder car j'appelle pas mal de procédures

    Merci
    Citation Envoyé par calou_33 Voir le message
    Bonjour,

    Sans doute. Je ne connaissais pas son existence

    Oui c'est ce que je fais déjà. Mais j'appelle application.processmessages pour rafraichir et ca me prend du cpu. Je voulais tester avec waitformul... qui parrait il est optimisée pour faire de l'attente

    Merci
    Application.processmessages peut aussi apporter des pb de réentrance. Si tu veux pas voir le petit voyant de ton gestionnaire des taches devenir tout vert tu peux rajouter un sleep(n) n tout petit, dans ta boucle de processmessages.

    Sinon le blocage de waitforxxxxxobject dans le thread principal de ton application bloque tout mais tu peux tout à fait créer un thread dans lequel tu va lancer tes autres thread. Donc pas de freez.

    Thread1
    procedure Execute
    Thread A
    Thread B
    Thread C
    waitformultipleObject
    .
    .
    .
    .


    L'interaction "inter-thread" d'un composant vcl doit être considéré avec soin.
    J'espère que tes query ne sont pas liés a une grille ou autre composant DBmachin. Sinon ça peux être le souk.
    Si tu as un composant commun entre tes query. Je n'ai jamais utilisé les IBCQUERY mais j'ai vu qu'il y avait un composant connexion et transaction. Il faut éviter d'utiliser le même pour tout tes query pour ne pas courir le risque de d'avoir des accès multiples asynchrones si tout ça n'est pas threadsafe.

    As tu vraiment l'utilité d'avoir n thread pour n query et pas un thread qui exécuterais toutes tes query ?

Discussions similaires

  1. etat d'un thread et WaitForMultipleObjects
    Par d'Oursse dans le forum Windows
    Réponses: 3
    Dernier message: 21/04/2011, 10h39
  2. [WD15] WaitForMultipleObjects dans un thread bloque mon application
    Par peijnoob dans le forum WinDev
    Réponses: 1
    Dernier message: 22/04/2010, 11h39
  3. WaitForMultipleObjects version Boost.Threads
    Par raphael_kindt dans le forum Boost
    Réponses: 1
    Dernier message: 17/09/2008, 15h35
  4. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 09h00
  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