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 :

Indy et Threads : Readln bloquant.


Sujet :

Langage Delphi

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Février 2003
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Indy et Threads : Readln bloquant.
    Bonjour,


    Je débute avec Indy et les threads et j'ai un soucis.
    Je dois traiter des données qui arrivent par réseau et par paquets à une certaine fréquence. Par exemple toutes les secondes (mais je ne peux connaitre cette fréquence, elle est paramétrée par le serveur a l'envoi, et je ne contrôle pas ce serveur) je reçois un ensemble de 30 lignes qu'il faut que je parse et que je traite.

    J'ai donc créé un thread dans lequel j'instancie un TIdTCPClient. Je le connecte au serveur et je boucle sur la reception.

    Mon soucis est que le programme se bloque sur le TIdTCPClient.ReadLn() jusqu'a la reception du paquets de données suivant. Je pensais qu'en mettant ces traitements dans un thread mon appli (en fait l'accès aux boutons, listes menus etc...) ne seraient pas bloqués or il le sont... et comme la fréquence de réception des données peut varier jusqu'a plusieurs minutes c'est très génant ^^

    Donc je voulais savoir, y'a-t-il un moyen d'isoler complètement l'exécution de ce thread de réception de données ?
    Ou bien y'a-t-il un moyen de savoir si le buffer a reçu quelque chose avant d'exécuter le readln ?


    Pour le moment la boucle de ma méthode Execute ressemble à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        while (true) do begin
      Application.ProcessMessages;
      ReceiveData; // methode qui contient le fameux TIdTCPClient.ReadLn() 
        end;

    Merci de votre aide je sèche un peu la :/

  2. #2
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Salut
    Tout d'abord :
    Citation Envoyé par AraXav
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
        while (true) do begin
    Euh c'est normal que ça ne marche pas ça... Donne une version un peu plus longue de ton code (avant surtout )

  3. #3
    DMO
    DMO est déconnecté
    Membre averti
    Avatar de DMO
    Profil pro
    Inscrit en
    Février 2004
    Messages
    290
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 290
    Points : 343
    Points
    343
    Par défaut
    Salut,

    Le comportement par défaut de ReadLn est en effet d'attendre indéfiniment que l'on écrive dans la connexion.

    Par défaut, le ReadTimeOut est défini IdTimeOutDefault (-1 je crois). Tu peux le définir à IdTimeOutInfinite (-2 je crois) de sorte que toute lecture dans la connexion se comporte comme le ReadLn.

    Mais dans ton cas, ce qui t'intéresse c'est que le ReadLn n'attende pas indéfiniment. Tu peux le faire en utilisant une version surchargée, ou en définissant le ReadTimeOut pour tout le monde (je préfère la première solution).

    Exemple avec 100 ms de TimeOut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vReceived := IdTCPClient1.IOHandler.ReadLn(LF, 100);
    Autre exemple avec 100 ms de TimeOut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      IdTCPClient1.ReadTimeout := 100;
      vReceived := IdTCPClient1.IOHandler.ReadLn;

  4. #4
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Points : 1 608
    Points
    1 608
    Par défaut
    Si le thread est bien programmé, il n'interfère pas avec le thread principal de l'application, celui qui dessine les contrôles à l'écran.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while (true) do begin
      Application.ProcessMessages;
      ReceiveData; // methode qui contient le fameux TIdTCPClient.ReadLn() 
        end;
    1. Pas de while "true". Une boucle infinie, même dans un thread, reste une boucle infinie. C'est à dire 100% du CPU utilisé pour ton programme...

    2. Application.ProcessMessages est strictement inutile. Ton thread n'a pas besoin de demander le traitement des messages car d'une part, ce n'est pas son affaire (il n'a pas de messages à recevoir) et d'autre part, que le thread principal s'occupe très bien de ça.

    3. ReceiveData.. Y'a quoi dedans ? C'est sûrement le problème. Moi je réecrirais ça comme ça :

    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 TMyThread.Execute; override;
    var
      S: string; //la donnée reçue
    begin
       with TIdTCPClient.Create do
       try
          //Configuration du socket
          Host := '127.0.0.1';
          Port := 1985; //au pif
          while not Terminated do //tant que le thread n'est pas arrêté...
          begin
             S := ReadLn();
             NotifyDataReceived(S); //Notifier au thread principal qu'on a reçu quelque chose...
          end;
       finally
          Free;
       end;
    end;

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2003
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Février 2003
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Bonjour

    Merci de vos réponses je vois que je fais fausse route dans pas mal de points !

    En fait les boucles while(true) m'ont paru un peu bizarres mais j'ai vu plusieurs exemples de ce type sur le net donc je me suis dit tentons ! ^^

    Comme c'est plutot pour un test je pars un peu dans toutes les directions à la fois.

    En tout cas une nouvelle fois merci, je vais intégrer vos suggestions et voir ce que ca va donner.

    @ bientôt

Discussions similaires

  1. [thread] Webservice Bloquant
    Par DaMo` dans le forum Windows Presentation Foundation
    Réponses: 2
    Dernier message: 29/10/2008, 11h07
  2. Indy 10 : IOHandler.Readln() vs. IOHandler.InputBufferAsString
    Par jackfirst72 dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 15/08/2008, 14h13
  3. [Débutant] Thread non bloquant
    Par GoustiFruit dans le forum Langage
    Réponses: 4
    Dernier message: 28/11/2007, 17h08
  4. Indy Terminate Thread Timeout
    Par FredKaes dans le forum Web & réseau
    Réponses: 3
    Dernier message: 16/10/2007, 10h52
  5. [MFC] thread : erreur bloquante
    Par Joeleclems dans le forum MFC
    Réponses: 4
    Dernier message: 20/05/2005, 13h58

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