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 :

Comportement différent Debug/Release dans un thread


Sujet :

Langage Delphi

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2010
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2010
    Messages : 60
    Points : 78
    Points
    78
    Par défaut Comportement différent Debug/Release dans un thread
    Bonjour à tous,

    Je rencontre depuis quelques jours un problème.

    J'ai un thread qui exécute une procédure avant de lancer un Chrono une fois que la procédure est finie.

    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
     
    TMonThread.MaProcedure;
    begin
      repeat
        // Traitement
      until BonTraitement;
    end;
     
    TMonThread.Execute;
    var
      Chrono:TChrono;
    begin
      MaProcedure;
      Chrono:=TChrono.Create;
      Chrono.SetInitTime;
     
      repeat
        // Traitement avec le temps du chrono différent selon Debug/Release
      until Terminated;
    end;
    En mode Debug, j'ai bien un temps à 0 une fois que la procédure est finie, alors qu'en mode Release j'ai le temps égal au temps qu'a mis ma procédure pour se terminer.

    Avez-vous une idée et une solution pour ce problème ?

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Remplace le TChrono par un TStopwatch pour commencer si tu as Delphi 2010, XE ou plus !

    A quoi sert le Chrono ?
    A la vue du code, tu as un Chrono mais tu n'en fait rien !

    Tu as deux boucles, une pour une première série et une autre boucle pour d'autres traitements ?
    A quoi sert la seconde boucle ?

    Qui arrête le thread ? un autre thread (le main thread compris) ?
    Terminated ne change pas de valeur tout seul, c'est quelque chose qui modifie cela pour arrêter le thread !
    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

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2010
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2010
    Messages : 60
    Points : 78
    Points
    78
    Par défaut
    Bonjour et merci pour la réponse.

    Désolé mais j'ai mis un code très vite fait qui ne correspond à rien. C'était juste pour expliquer l'idée que l'appel à la procédure "MaProcedure" était différent en mode Debug ou Release.

    Remplace le TChrono par un TStopwatch pour commencer si tu as Delphi 2010, XE ou plus !
    Ok merci, je ne connaissais pas. J'utilise mon propre Chrono qui utilise TimeGetTime de MMSystem pour récupérer le temps et le comparer à un temps initial pour en faire un chrono.

    A quoi sert le Chrono ?
    A la vue du code, tu as un Chrono mais tu n'en fait rien !
    J'utilise le Chrono pour afficher des résultats dans un graphe en fonction du temps. Je mesure quelques données et je les affiche en fonction du temps lors de mon traitement dans TMonThread.Execute

    Tu as deux boucles, une pour une première série et une autre boucle pour d'autres traitements ?
    A quoi sert la seconde boucle ?
    La première boucle est pour attendre une condition. Je ne veux pas lancer ma boucle principale tant que je n'ai pas cette condition.
    Et je ne veux pas non plus démarrer le chrono avant d'avoir la condition dans MaProcedure. En mode Debug, ça fonctionne tandis qu'en mode Release, mon Chrono est lancé.
    La boucle dans Execute est mon traitement principal (mesure de données et affichage).

    Qui arrête le thread ? un autre thread (le main thread compris) ?
    Terminated ne change pas de valeur tout seul, c'est quelque chose qui modifie cela pour arrêter le thread !
    Mon thread est arrêté sur un temps ou sur un clic de l'utilisateur. Je n'ai pas pris le temps de mettre la condition, j'ai juste mis Terminated pour faire plus rapide... Mais l'arrêt ne me pose pas de problème.

    J'espère avoir été un peu plus clair, désolé de ne pas avoir pris le temps d'expliquer un peu plus la situation

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par DuffNut Voir le message
    Désolé mais j'ai mis un code très vite fait qui ne correspond à rien. C'était juste pour expliquer l'idée que l'appel à la procédure "MaProcedure" était différent en mode Debug ou Release.
    Tu n'aurais pas oublié dans le code un truc pour le débogage ?
    Cela m'arrive, en Debug, je raccourci les délais de patience de mes threads parce que je veux tester rapidement et passer mon temps à attendre !

    Citation Envoyé par DuffNut Voir le message
    J'utilise le Chrono pour afficher des résultats dans un graphe en fonction du temps. Je mesure quelques données et je les affiche en fonction du temps lors de mon traitement dans TMonThread.Execute.
    D'accord, tu as une notion de temps dans la récupération de données, on peut donc ignorer la seconde boucle

    Citation Envoyé par DuffNut Voir le message
    La première boucle est pour attendre une condition. Je ne veux pas lancer ma boucle principale tant que je n'ai pas cette condition.
    Si la condition provient d'un autre thread qui change une valeur quelque part, j'utiliserais un TEvent pour notifier au Thread de démarrer, c'est le principe des Signaux\Sémaphore !
    Le Thread qui modifie le contexte invoque SetEvent et pendant de temps, le thread de traitement lui est en pause via WaitFor

    En RELEASE, le code est plus rapide qu'en DEBUG lancé via Delphi
    As-tu essayé en DEBUG hors Delphi, le code est un poil plus lent pour deux-trois optimisations mais c'est bien plus proche du RELEASE
    Car oui, lancé en DEBUG via Delphi cela ralenti énormément puisque Delphi surveille le programme (les threads, la pile d'appel, les variables locales ...) et le comportement mutli-thread est faussé
    Evidemment en mode pas à pas, là, c'est totalement faussé, on peut passer des heures en DEBUG a ne jamais reproduire un problème de dead-lock de thread qui ne produira jamais en DEBUG !

    Citation Envoyé par DuffNut Voir le message
    Et je ne veux pas non plus démarrer le chrono avant d'avoir la condition dans MaProcedure. En mode Debug, ça fonctionne tandis qu'en mode Release, mon Chrono est lancé.
    Du coup, on a plutôt l'impression que c'est TChrono qui bugge comme si valeur dans le Create ou SetInitTime était mal renseigné !
    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

  5. #5
    Membre régulier
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2010
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2010
    Messages : 60
    Points : 78
    Points
    78
    Par défaut
    J'ai trouvé le problème mais je vais répondre à tes remarques :

    Citation Envoyé par ShaiLeTroll Voir le message
    Tu n'aurais pas oublié dans le code un truc pour le débogage ?
    Cela m'arrive, en Debug, je raccourci les délais de patience de mes threads parce que je veux tester rapidement et passer mon temps à attendre !
    Non je n'ai pas mis de définitions conditionnelles si c'est ça que tu voulais dire.

    Citation Envoyé par ShaiLeTroll Voir le message
    En RELEASE, le code est plus rapide qu'en DEBUG lancé via Delphi
    As-tu essayé en DEBUG hors Delphi, le code est un poil plus lent pour deux-trois optimisations mais c'est bien plus proche du RELEASE
    Car oui, lancé en DEBUG via Delphi cela ralenti énormément puisque Delphi surveille le programme (les threads, la pile d'appel, les variables locales ...) et le comportement mutli-thread est faussé
    Evidemment en mode pas à pas, là, c'est totalement faussé, on peut passer des heures en DEBUG a ne jamais reproduire un problème de dead-lock de thread qui ne produira jamais en DEBUG !
    J'ai essayé toutes les configs DEBUG sans ou avec Delphi et les résultats étaient toujours pareils : en mode DEBUG c'était bon mais pas en mode RELEASE.

    Citation Envoyé par ShaiLeTroll Voir le message
    Si la condition provient d'un autre thread qui change une valeur quelque part, j'utiliserais un TEvent pour notifier au Thread de démarrer, c'est le principe des Signaux\Sémaphore !
    Le Thread qui modifie le contexte invoque SetEvent et pendant de temps, le thread de traitement lui est en pause via WaitFor
    J'avais déjà utilisé cette méthode pour faire le même genre de choses mais je n'y ai absolument pas pensé, merci !

    Du coup, j'ai remplacé tous mes TChrono par des TStopwatch : même problème.

    Puis j'ai implémenté un nouveau thread pour mon traitement qui attend la condition, avec le déclenchement d'un TEvent à la fin pour pouvoir lancer ma boucle principale : même problème !

    En fait c'est tout con :

    Dans mon thread qui attend une condition, j'attends qu'une variable prenne la valeur 0. Or, je ne l'avais pas initialisé... Et j'ai l'impression qu'en mode Debug elle s'initialisait à une valeur différente de 0 alors qu'en mode Release elle était directement initialisée à 0... Je ne sais pas si ça peut être possible mais en tout cas, après l'avoir initialisée à 1, je n'ai plus de soucis...

    Une bonne erreur à la c**

    Merci à toi pour tes explications, ça m'a au moins permis de découvrir TStopwatch et de repenser au TEvent (que j'utilisais un peu plus haut dans mon code mais auquel je n'avais pas pensé pour ce cas là) et donc d'avoir un code un peu plus propre.

    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
     
    var
      MyEvent: TEvent;
     
    TMyWaitingThread.Execute;
    var
      err:integer;
    begin
      err:=1; // Initialisation
     
      repeat
        // Changement de la variable err selon des critères...
      until (err=0);
     
      MyEvent.SetEvent;
    end;
     
    TMyMainThread.WaitCondition;
    begin
      MyEvent.ResetEvent;
     
      MyWaitingThread:=TMyWaitingThread.Create;
     
      if MyEvent.WaitFor(60000) <> wrSignaled then begin
        // Traitement si on a pas eu la bonne condition au bout de 60 secondes...
      end;
     
      MyWaitingThread.Terminate;
      MyWaitingThread.WaitFor;
      FreeAndNil(MyWaitingThread);
    end;
     
    TMyMainThread.Execute;
    begin
      WaitCondition;
     
      repeat
        // Traitement avec mesure et affichage de données
      until Chrono.Elapsed.TotalSeconds > TempsMax;
    end;
    Voilà l'idée principale en code... Par contre lorsque j'ai pas ma condition au bout des 60 secondes, je demande à l'utilisateur s'il veut attendre de nouveau. Si non je quitte tout et je ne fais pas mon traitement principal. Si oui, je veux recommencer l'attente. Quel est le plus beau moyen de faire cela ? Car pour l'instant j'ai mis un goto qui retourne avant le WaitFor de l'event...


    Sujet résolu même si finalement c'était un problème d'initialisation...

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

Discussions similaires

  1. VS2008 Comportement différent entre debug et release
    Par Ardis dans le forum Visual Studio
    Réponses: 1
    Dernier message: 19/03/2011, 09h41
  2. Dll avec un nom différent en release et debug
    Par julien.sagnard dans le forum C++Builder
    Réponses: 0
    Dernier message: 23/01/2008, 12h24
  3. [C#][2.0] Sauvegarde d'un DataSet dans des threads différents
    Par Pilloutou dans le forum Framework .NET
    Réponses: 9
    Dernier message: 23/04/2007, 14h17
  4. Rafraichissement différent Debug et Release
    Par cheachwood dans le forum Visual Studio
    Réponses: 2
    Dernier message: 06/12/2006, 17h01
  5. [VB.NET] Création MDIChild dans un thread différent
    Par XnoTonio dans le forum Windows Forms
    Réponses: 5
    Dernier message: 19/05/2006, 15h53

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