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

API, COM et SDKs Delphi Discussion :

Problème avec TThread


Sujet :

API, COM et SDKs Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de Onimaru
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2010
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Turquie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2010
    Messages : 283
    Par défaut Problème avec TThread
    Salut à tous, voici mon problème :
    Pour ne pas mobiliser l'interface d'un programme j'ai utilisé un objet de type "TThread" pour faire un calcul long. Tout marche bien sauf que moi je veux que, en cas d'un arrêt manuel ou automatique du traitement, le thread se libère (Dans la partie qui gère les threads et les processus du système d'exploitation) et que l'objet "TThread" se libère (par le destructeur) aussi et qu'il devienne "nil" "FreeAndNil".

    D'après ce que j'ai lu, il faut insérer des tests sur "Terminated" dans "Execute" :
    Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
       if Terminated then
        Exit;
    pour pouvoir arrêter le thread en plein travail, ça marche bien.

    Je me demande s'il faut mettre quelque chose à la fin de la méthode surchargée "Execute" pour indiquer que le traitement est terminé ???

    D'après ce que je sais "Terminated" devient automatiquement "True" à la fin de "Execute".

    Est ce que "FreeOnTerminate" libère l'objet TThread ???

    Où se situe le déclenchement de "OnTerminate" ??? est ce entre la fin du traitement du thread et la destruction de l'objet ???

    Bref je veux un "FreeAndNil" automatique à la fin du traitement d'un thread comment faire ???

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 086
    Par défaut
    FreeOnTerminate libère le thread, cela fonctionne très bien, évite par contre de mémoriser l'instance (sinon gérer dans un OnTerminate la mise à nil de la référence) car c'est violation d'accès assurée sinon !
    Tu peux utiliser un TEvent pour gérer aussi une éventuel synchro avec d'autres thread !

    OnTerminate se produit après le Execute AVANT la destruction !
    C'est lancé via un Synchronize dans le Main !

    Les Delphi récents fournissent Finished pour indiquer la fin du thread, tu peux le faire toi même avec un boolean en propriété du thread mis à False par défaut et mis à True à la fin du Execute !

    je pense que ton code sera

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    procedure TShinichi.LancerThread();
    begin
      Reference := TOnimaruThread.Create(True);
      Reference.FreeOnTerminate := True;
      Reference.OnTerminate := OnimaruThreadTerminate;
      Reference.Start(); // Resume pour les anciens Delphi 
    end;
     
    procedure TShinichi.OnimaruThreadTerminate(Sender: TObject);
    begin
      if Sender = Reference then
        Reference := nil;
    end;

    TShinichi est un objet, cela peut-être une TForm
    OnimaruThreadTerminate est un TNotifyEvent, méthode privée de TShinichi
    Reference est un membre privé de TShinichi
    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 éclairé Avatar de Onimaru
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2010
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Turquie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2010
    Messages : 283
    Par défaut
    Merci pour le message,
    En effet c'est la situation que j'ai :

    J'ai un objet de type "TShinichi" qui contient un thread de type "TOnimaru" qui fait le calcul. Ce thread est appelé "FThread".
    Or "TOnimaru" contient une référence vers un objet de type "TShinichi" appélée "FShinichi" pour permettre au thread de travailler avec les méthodes et les données de l'objet "TShinichi" qui l'appelle.

    Depuis que j'ai posté le message j'ai réfléchi et je suis arrivé à une solution semblable :
    Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    procedure TShinichi.LancerThread;
    begin  
      FThread := TOnimaruThread.Create(True);
      FThread.FreeOnTerminate := True;
      FThread.FShinichi := Self; // L'objet appelant le thread.
      FThread.OnTerminate := OnimaruThreadTerminate;
      FThread.Start() // J'ai CodeGear Delphi XE2 :)
    end;

    Sauf que dans OnimaruThreadTerminate j'ai mis seulement le code de nettoyage.

    J'ai déplacé "FThread := Nil" dans "Destroy" de "TOnimaru" comme suit :
    Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    destructor TOnimaru.Destroy;
    begin
     FShinichi.FThread := Nil;
     inherited Destroy
    end;

    Et ça a marché, toutefois votre solution semble meilleure.
    Merci encore.

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 086
    Par défaut
    Ah, tu avais des références croisées !
    FThread (équivalent de mon Reference) dans TShinichi
    Mais aussi FShinichi dans TOnimaru

    C'est un problème classique de durée de vie d'un objet lorsqu'il est partagé par plusieurs threads et qu'il y a inter-dépendance !

    En général, je modifie le constructeur pour lui passer en paramètre les objets dont le thread a besoin, cela évite le Suspended et le Start car le thread ne démarre qu'au AfterConstruction donc après tous les constructeurs hérités !

    J'évite l'accès à des membres privés ou protégés entre les objets (essaye d'utiliser strict private le plus que possible), je privilégie des accesseurs en lecture seule ou des méthodes, par exemple, encore plus depuis que je suis en C++Builder, c'est strict pas nature !


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TShinichi.LancerThread;
    begin  
      FThread := TOnimaruThread.Create(this, OnimaruThreadTerminate);
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    constructor TOnimaru.Create(AShinichi: TShinichi; ATerminateEventHandler: TNotifyEvent);
    begin
      inherited Create(false);
      FreeOnTerminate := True;
      FShinichi := AShinichi; // L'objet appelant le thread.
      OnTerminate := ATerminateEventHandler;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    destructor TOnimaru.Destroy;
    begin
     FShinichi.NotifyThreadDestroy(this);
     
     inherited Destroy();
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TShinichi.NotifyThreadDestroy(AThread: TOnimaru);
    begin  
      if FThread = AThread then
        FThread := nil;
    end;
    Ainsi si tu prévois demain de gérer plusieurs threads dans TShinichi, tu n'auras pas à modifier le code de TOnimaru car il utilise une méthode qui masque l'implémentation de TShinichi
    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 éclairé Avatar de Onimaru
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2010
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Turquie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2010
    Messages : 283
    Par défaut
    Merci pour cet éclaircissement, je vais faire comme vous avez dit.
    Toutefois pouvez vous me dire la différence entre "private" et "strict private" et par la même occasion "published" et "automated" (je touche l'orienté objet) ?

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 086
    Par défaut
    Je t'ai donné un lien dans ma réponse Classes and Objects (Delphi) - Strict Visibility Specifiers
    Lit l'ensemble de la page !

    le Private, seul l'objet peut accéder à ces membres !
    Attention, toutes les classes étant définies dans le même fichier peut aussi accéder au membre privé ! un peu comme si toute les classes d'une même unité était considéré comme des "classes amies" (voir java\c++)
    Je pense que Delphi doit être l'un des rares langages Orienté Objet à fournir cette "souplesse"

    le Strict Private, seul l'objet et uniquement lui peut accéder à ces membres !
    Cela correspond au Private du Java\C++

    Avant, il n'y avait que "private", Delphi était assez permissif, le "strict private" force le développeur à un meilleur respect de la POO et des "Design Pattern"
    Ces dernières fournissent des règles pour l'interaction entres les objets, perso, je n'en applique que très peu tout simplement parce que je ne sais pas laquelle doit être utilisé à quel moment et pour quel objectif
    En Delphi, il très facile de faire une Anti-Pattern Programmation spaghetti et Action à distance
    Personnellement, je crois que je suis très doué pour les lasagnes et les spaghettis avec mes Objets



    Published, c'est plus complexe, cela implique les RTTI et tout le mécansime de sérialization des TForm en DFM ( et encore plein d'autre chose )
    Cela serait l'équivalent Delphi de la Reflexion du .NET, c'est un raccourci un peu grossier, mais c'est l'idée !

    Voir TObject.MethodAddress et TObject.FieldAddress
    Voir TPersistent, TComponent et TStream.ReadComponent ou encore TRemotable

    automated ? euh c'est pour les Objets Automation ?
    Oublie, ce n'est pas très important ! il y a d'autres façon de faire ! En général, avec l'éditeur de Bibliothèque des types, cela se fait tout seul !
    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

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

Discussions similaires

  1. Problème avec TThread
    Par Mccleen dans le forum C++Builder
    Réponses: 4
    Dernier message: 26/05/2013, 00h15
  2. [TThread] Problème avec l'évènement OnTerminate
    Par coax81 dans le forum Langage
    Réponses: 12
    Dernier message: 05/11/2007, 14h05
  3. Problème avec le type 'Corba::Any_out'
    Par Steven dans le forum CORBA
    Réponses: 2
    Dernier message: 14/07/2002, 18h48
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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