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

Delphi Discussion :

Blocage même avec Application.ProcessMessages


Sujet :

Delphi

  1. #1
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut Blocage même avec Application.ProcessMessages
    Salut!

    J'ai un problème de "multitâche" avec un code du genre :
    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
    {----------------------------------------------------------------}
    procedure Boucle(Lab: TLabel);
    Var x: Integer;
    Begin
      Repeat
        x := StrToIntDef(Lab.Caption, 0) + 1;
        Lab.Caption := IntToStr(x);
        Application.ProcessMessages;
        Sleep(200);
      Until(x > 500);
    End;
     
    {----------------------------------------------------------------}
    procedure TForm1.Button1Click(Sender: TObject);
    begin
     If (Label1.Caption = 'Label1') Then Begin Boucle(Label1); Exit; End;
     If (Label2.Caption = 'Label2') Then Begin Boucle(Label2); Exit; End;
    end;
    La 1ère boucle se lance bien lorsqu'on clique sur le bouton, mais se bloque lorsqu'on lance la 2ème boucle... Je pensais qu'Application.ProcessMessages suffisait dans ce cas... Existe-t-il une solution pour que les 2 boucles fonctionnent simultannément sans utiliser les threads ?

    Sinon, quelle est le code le plus simple pour résoudre ce problème ?

    Merci d'avance.
    De retour parmis vous après 10 ans!!

  2. #2
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 288
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 288
    Points : 1 936
    Points
    1 936
    Par défaut
    S'il y a une solution je suis intéressé. Mais j'en doute, étant donné que c'est le même processus qui lance les deux fonctions.
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  3. #3
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    J'ai réalisé ceci (avec un thread). Le code vous semble-t-il bon ?
    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
    Unit Unit1;
    Interface
    Uses Windows, Messages, SysUtils, Classes, Graphics, Controls,
         Forms, Dialogs, StdCtrls;
     
    Type
      TForm1 = Class(TForm)
        Button1: TButton;
        Label1: TLabel;
        Label2: TLabel;
        Procedure Button1Click(Sender: TObject);
      End;
     
      TMyThread = Class(TThread)
        CurLab: TLabel;
      Protected
        Procedure Execute; Override;
      End;
     
    Var Form1: TForm1;
     
     
    {----------------------------------------------------------------}
    {                       }Implementation{                         }
    {----------------------------------------------------------------}
    {$R *.dfm}
     
    Var th1, th2: TMyThread;
     
     
    {----------------------------------------------------------------}
    Procedure TMyThread.Execute;
    Var x: Integer;
    Begin
      Repeat
        x := StrToIntDef(CurLab.Caption, 0) + 1;
        CurLab.Caption := IntToStr(x);
        Application.ProcessMessages;
        Sleep(200);
      Until (x >= 100);
      FreeAndNil(self);
    End;
     
    {----------------------------------------------------------------}
    Procedure Boucle(th: TMyThread; Lab: TLabel);
    Begin
      th := TMyThread.Create(False);
      th.CurLab := Lab;
    End;
     
    {----------------------------------------------------------------}
    Procedure TForm1.Button1Click(Sender: TObject);
    Begin
      If (Label1.Caption = 'Label1') Then Begin Boucle(th1, Label1); Exit; End;
      If (Label2.Caption = 'Label2') Then Begin Boucle(th2, Label2); Exit; End;
    End;
     
    {----------------------------------------------------------------}
    End.
    De retour parmis vous après 10 ans!!

  4. #4
    Modérateur
    Avatar de Rayek
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    5 235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Savoie (Rhône Alpes)

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 235
    Points : 8 504
    Points
    8 504
    Par défaut
    Citation Envoyé par Sub0
    La 1ère boucle se lance bien lorsqu'on clique sur le bouton, mais se bloque lorsqu'on lance la 2ème boucle... Je pensais qu'Application.ProcessMessages suffisait dans ce cas... Existe-t-il une solution pour que les 2 boucles fonctionnent simultannément sans utiliser les threads ?

    Sinon, quelle est le code le plus simple pour résoudre ce problème ?

    Merci d'avance.
    Au vu du code, je te dirais un gros non, vu que c'est du traitement séquentiel que tu fais (tant que le premier n'a pas fini ca ne passera pas à la suite), le Application.ProcessMessages ne sert qu'a laissé passer les message windows pour le rafraichissement de ta form et les applications à coté.

    Si tu veux que les 2 se lancent en même temps, il va te falloir un thread.
    Sinon tu peux utiliser les TJvThread de la JVCL qui est simple d'utilisation pour le fonctionnement que tu veux faire.
    Modérateur Delphi

    Le guide du bon forumeur :
    __________
    Rayek World : Youtube Facebook

  5. #5
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Citation Envoyé par Malatar
    Au vu du code, je te dirais un gros non, vu que c'est du traitement séquentiel que tu fais (tant que le premier n'a pas fini ca ne passera pas à la suite), le Application.ProcessMessages ne sert qu'a laissé passer les message windows pour le rafraichissement de ta form et les applications à coté. Si tu veux que les 2 se lancent en même temps, il va te falloir un thread.
    Merci pour vos réponses. J'avais peu d'espoir de pouvoir le faire sans thread... je suis fixé maintenant.
    Citation Envoyé par Malatar
    Sinon tu peux utiliser les TJvThread de la JVCL qui est simple d'utilisation pour le fonctionnement que tu veux faire.
    Alors j'ai quelques questions à ce propos :
    • Quels avantages / inconvéniants de TJvThread par rapport au code donné ci-dessus ?
    • La fonction synchronize est-elle indispensable dans un thread ?
    • Mon code fonctionne, mais est-il "propre" selon vous ?
    De retour parmis vous après 10 ans!!

  6. #6
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 288
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 288
    Points : 1 936
    Points
    1 936
    Par défaut
    J'aurais plutôt initialisé le Thread avec un FreeOnTerminate à True après le Create
    et à la place du FreeAndNil, j'aurais mis un Terminated := True.

    Pour le synchronize, normalement il est indispensable pour tout interaction avec le thread principal (et donc l'aspect graphique il me semble). Mais pour quelle raison, je ne sais pas.
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  7. #7
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    582
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2003
    Messages : 582
    Points : 915
    Points
    915
    Par défaut
    J'ai un petit problème lorsque tu créer ton thread...
    Citation Envoyé par Aide de delphi
    If CreateSuspended is False, Execute is called immediately
    donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Procedure Boucle(th: TMyThread; Lab: TLabel);
    Begin
      th := TMyThread.Create(False); // selon la citation, Ton thread peut ici être lancé sans que CurLab soit initialisé...
      th.CurLab := Lab;
    End;
    je crois qu'il serait préférable de surchargé le create du thread ou de le créer suspendu comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Procedure Boucle(th: TMyThread; Lab: TLabel);
    Begin
      th := TMyThread.Create(TRUE); // Creation en mode suspendu 
      th.CurLab := Lab;                   // Initialisation des variables du thread
      th.Resume;                       //Permet ici l'execution du thread.
    End;
    ensuite vient le synchronise qu'on doit utiliser surtout lorsqu'on effectue
    des changements dans le thread principale.
    (On pourrait-être en train d'affiché le label dans le thread principale lorsqu'on le modifie dans notre 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
    procedure TMyThread.SetCaption;
    begin
      CurLab.Caption := IntToStr(x);
    end;
    
    Procedure TMyThread.Execute;
    Begin
      FreeOnTerminate:=TRUE;     // Indique qu'on veut libirer le thread automatiquement lorsqu'il est terminé.
    
      Repeat
        x := StrToIntDef(CurLab.Caption, 0) + 1;
        Synchronize(SetCaption);
        Sleep(200);
      Until (x >= 10) or (Terminated);
      //Le thread ce termine lorqu'on quitte Execute.
    End;
    C'est une bonne habitude de verifier la variable Terminated dans la boucle du thread.

    la déclaration de la classe devient ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    TMyThread = Class(TThread)
        CurLab: TLabel;
      Protected
        x: Integer;
        Procedure Execute; Override;
        procedure SetCaption;
      End;
    Voilà, c'est mieux ainsi je crois...
    Comment dupliquer un disque...ça vous intéresse?
    Tutoriel et code source delphi ici

  8. #8
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Excelent!

    Grâce à tes conseils, j'ai solutionné le problème dans mon programme!
    Merci à tous!
    De retour parmis vous après 10 ans!!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. petit problème avec Application.ProcessMessages
    Par tornade69 dans le forum Langage
    Réponses: 4
    Dernier message: 09/10/2008, 15h27
  2. blocage de l'application avec javax.comm
    Par caloun62 dans le forum Entrée/Sortie
    Réponses: 1
    Dernier message: 19/03/2007, 19h59
  3. Réponses: 1
    Dernier message: 01/01/2006, 19h53
  4. problème avec Application->ProcessMessages()
    Par petitours dans le forum C++Builder
    Réponses: 4
    Dernier message: 15/08/2005, 10h27
  5. [WIN2000][JAVA]blocage de l'application
    Par narmataru dans le forum InterBase
    Réponses: 9
    Dernier message: 09/12/2003, 13h07

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