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

Web & réseau Delphi Discussion :

http get fait freezer ma main form quelques secondes


Sujet :

Web & réseau Delphi

  1. #1
    Membre à l'essai Avatar de myflash
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juillet 2011
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

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

    Informations forums :
    Inscription : juillet 2011
    Messages : 55
    Points : 16
    Points
    16
    Par défaut http get fait freezer ma main form quelques secondes
    J'ai fait un exemple vite fait pour illustrer un de mes problemes dans un logiciel que je suis en train de faire.

    Quand on fait un http get, le main form freeze tant qu'on n'a pas la réponse. Voici un exemple qui fait figer le form :
    J'ai mis un loop de 5 pour que ça représente mieux mon problème car dans mon logiciel j'ai plusieurs valeurs à aller chercher sur le serveur, donc plusieurs get les uns après les autres.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    uses 
        IdHTTP, Threading;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    var
        HTTP: TIdHTTP;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        for tempind := 0 to 5 do
        begin
            try
                Memo1.Text := Memo1.Text + HTTP.Get('https://fapi.binance.com/fapi/v1/exchangeInfo') + #13#10;
            except
                on E: Exception do ShowMessage(E.Message)
            end;
        end;
    J'ai essayé de wrapper mes get avec des TTask.Run. C'est ok, mais, vu que ça fait plusieurs get les uns après les autres, il n'a pas fini le premier get avant de faire le 2ème get... Ça part en couille d'erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
        for tempind := 0 to 5 do
        begin
            TTask.Run(
                procedure
                begin
                    try
                        Memo1.Text := Memo1.Text + HTTP.Get('https://fapi.binance.com/fapi/v1/exchangeInfo') + #13#10;
                    except
                        on E: Exception do ShowMessage(E.Message)
                    end;
                end);
        end;
    Une solution est de mettre le loop à l'intérieur du task, mais je ne peux pas faire ça, car les get viennent de plusieurs places différentes dans le programme.

    J'ai pensé à un système de queue à l'entrée de ma fonction gethttp, qui lui fait appel au http.get au fur et à mesure qu'il en a fini un.

    Par contre, le queuewait doit looper avec un while et un Application.ProcessMessages, sinon mon main freeze. Jusqu'ici avec un queue, un loop Application.ProcessMessages, un système de ttaks.run pour exécuter le get sans que ça freeze le main, c'est ok.

    J'ai eu des choses intéressantes qui sont ok avec le queue, mais, si je close ma fenêtre, ça appelle le destroy de mon queue, des fois il y a encore des get qui sont en ligne dans le queue. Je suis rendu au fait que je dois attendre que le queue soit tout fini avant de finir le destroy. Donc un while queue.count > 0 vous allez dire ou while not queue.empty lolll ben ça freeze mon main form encore. Si je ne veux pas que ça freeze mon main form, je dois ajouter un Application.ProcessMessages dans mon while ... Ça part en couille d'erreur, on ne peut pas faire Application.ProcessMessages, dans le destroy à cause du fait que l'application est en train de se fermer.

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    novembre 2002
    Messages
    8 949
    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 949
    Points : 29 156
    Points
    29 156
    Par défaut
    il va falloir apprendre à gérer les thread correctement.

    1) la boucle devrait être dans le thread

    2) on ne modifie pas un composant visuel depuis un Thread

    donc tu crées un Thread qui va lire toutes tes les infos dont il a besoin en autant de get que nécessaire, puis tu utilises Synchronize pour informer le thread principal que la requête est terminée.

    le plus simple est donc de créer un dérivé de TThread

    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
     
    type
      TMyThread = class(TThread) 
        Str: string;
        Form: Tform1;
        constructor Create(AForm: TForm1);
        procedure Done;
        procedure Execute; override;
      end;
     
    cosntructor TMyThread.Create(AForm: TForm1);
    begin
      Form := AForm;
      inherited create(False);
      FreeOnTerminate := True;
    end;
     
    procedure TMyThread.Execute;
    begin
       var http := TidHTTP.Create(nil);
       try
         for var i := 1 to 5 do
         begin
           Str := Str + HTTP.Get('https://fapi.binance.com/fapi/v1/exchangeInfo') + #13#10;
           if Terminated then Exit; // si on a stoppé le thread, 
         end;
         Synchronize(Done);
       finally
         http.Free;
       end;
    end;
     
    procedure TMyThread.Done;
    begin
      Form.Thread := nil; // indiquer à la fiche que le thread est terminé
      Form.Memo1.Text  := Str; // on utilise de préférence un constructeur pour donner l'instance de Form1 au thread
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre expert
    Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Inscrit en
    juin 2013
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : juin 2013
    Messages : 1 876
    Points : 3 609
    Points
    3 609
    Par défaut
    et si tu es en 10.2 Tokyo ou suivante, tu peux même utiliser TParallel.for() pour remplacer ta boucle (mais attention : chaque itération ne doit pas dépendre des précédentes), ce sera bloquant pur le code et soumet les itérations de ta boucle en ttask

    si tu tiens à ce que les choses se synchronisent tu peux aussi utiliser un ou plusieurs Event de System.Syncobjs

  4. #4
    Membre à l'essai Avatar de myflash
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juillet 2011
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

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

    Informations forums :
    Inscription : juillet 2011
    Messages : 55
    Points : 16
    Points
    16
    Par défaut
    Ouein c'est un peu ce que je pensais, un système de queue des appels http get qui sont executés un après l'autre dans un thread, puis retourner la valeur avec un système de callback...

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

Discussions similaires

  1. Impression qui fait freezer le programme
    Par Higestromm dans le forum Qt
    Réponses: 15
    Dernier message: 15/06/2007, 10h54
  2. envoyer une HTTP GET sans cURL
    Par Eusebius dans le forum Langage
    Réponses: 2
    Dernier message: 18/03/2007, 20h28
  3. Faire un HTTP GET en c++
    Par vivoli12 dans le forum C++
    Réponses: 2
    Dernier message: 24/08/2006, 13h00
  4. Un http get avec le shell...
    Par kitov dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 11/02/2006, 12h34
  5. Parser une requête HTTP/GET en c ! regex ?
    Par canard75 dans le forum C
    Réponses: 14
    Dernier message: 06/12/2005, 10h08

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