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

Composants VCL Delphi Discussion :

Acceder aux propriétés d'un composant depuis un thread


Sujet :

Composants VCL Delphi

  1. #1
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut Acceder aux propriétés d'un composant depuis un thread
    Bonjour,

    J'ai un thread qui execute un script dans mon application.
    Le script est une séquence d'instructions que l'utilisateur peut saisir.
    Grâce à ce script, l'utilisateur peut modifier les propriétés de certains composants de la fiche comme par exemple les aspects visuels (width, height...)
    Le problème est que lorsqu'on diminue la largeur de l'objet, le fond de la fenêtre est mal redessiné.
    Je pense que c'est à cause de l'utilisation du thread mais comment contourner ce problème ???

    merci

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 665
    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 665
    Points : 25 462
    Points
    25 462
    Par défaut
    Tu modifie une TForm depuis un Thread ?

    il est pourtant indiqué qu'il ne faut pas le faire sans Synchronize dans : Définition d'objets thread

    Important: Methods and properties of objects in visual components can only be
    used in a method called using Synchronize, for example,
    Synchronize(UpdateCaption);
    Je crois même que c'est un commentaire qui s'ajoute si l'on utilise l'expert Thread

    Ce script a-t-il vraiment besoin d'être lancé dans un thread ?
    De plus, difficile de t'aider, on ne connait pas le moteur de script utilisé ni ses capacités, ni ses limites ...

  3. #3
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    C'est bien ce que j'avais compris mais j'ai lancé une bouteille à la mer, au cas où...et là je me retrouve bien bloqué !
    Je n'avais pas structuré mon programme pour cela car jusqu'à présent j'utilisais un TTimer mais maintenant j'ai besoin de plus de rapidité et de précision alors je ne sais plus trop quoi faire...

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 665
    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 665
    Points : 25 462
    Points
    25 462
    Par défaut
    Méthode kamikaze !
    Ajoute des Appels à Refresh ou Invalidate dans le script
    OU
    Un application.ProcessMessages dans le thread, c'est horrible mais ça peu fonctionner (avec en prime des OS Error 1400 : Handle Invalid), ou alors ta propre boucle PumpMessage

    Méthode du Proxy :
    Il te faudrait gérer un objet intermédiaire (Proxy)
    Cet objet simule les propriétés de la TForm voulue (juste ce qui est utile)
    Tu lance le script qui modifie l'objet intermédiaire
    Une fois le script terminé, tu fais un Synchronize pour recopier l'objet intermédiaire vers la TForm concernée !

  5. #5
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    "Ajoute des Appels à Refresh ou Invalidate dans le script"
    Non je ne peux pas car je ne sais pas quels sont les propriétés de l'objet que l'utilisateur va modifier. J'ai fait un editeur de propriété qui affiche toutes les propriété des composants et l'utilisateur choisi celles qu'il veut modifier dans son script.

    application.ProcessMessages
    Je viens d'essayer de le mettre dans la procedure execute du thread mais ça ne change rien et puis dans cette procedure j'appelle sleep(1) qui à mon avis appelle ProcessMessages.

    La méthode du proxy
    Ce n'est pas exploitable dans mon application. En fait l'application est un environnement de développement avec lequel l'utilisateur peut créer ses propres fiches, disposer ses propres composants et executer des scripts sur les évènements des composants (évènements de la VCL: OnClick, OnMouseDown etc..) Et il peut acceder à toutes le propriétés des composants (propriétés de la VCL) dans ses scripts.

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 665
    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 665
    Points : 25 462
    Points
    25 462
    Par défaut
    Citation Envoyé par franckcl Voir le message
    "Ajoute des Appels à Refresh ou Invalidate dans le script"
    Non je ne peux pas car je ne sais pas quels sont les propriétés de l'objet que l'utilisateur va modifier. ...
    Un Invalidate sur le component Racine pas sur les sous-éléments !

    Citation Envoyé par franckcl Voir le message
    application.ProcessMessages
    Je viens d'essayer de le mettre dans la procedure execute du thread mais ça ne change rien et puis dans cette procedure j'appelle sleep(1) qui à mon avis appelle ProcessMessages.
    Change d'avis alors, car ce n'est PAS DU TOUT ÇA !
    Sleep est une API Windows qui coupe totalement l’exécution d'un thread, cela n'a rien à voir avec ProcessMessages qui un Code Delphi composée d' une boucle qui écoute les messages via les API Windows WaitMessage\PeekMeesage\TranslateMessage\DispatchMessage

    Citation Envoyé par franckcl Voir le message
    La méthode du proxy
    Ce n'est pas exploitable dans mon application.
    Tu uilises ton propre moteur de script ou un produit comme Pascal Script ou TMS Scripter Studio
    J'avais utilisé DreamScript ou Greatis Script plus des composants reproduisant l'inpecteur d'objet, le Design Editor dans des configurateurs d'écran, une problèmatique qui revient souvent lorsque l'on gère une application genre une CRM et qui nécessite une adaptabilité aux problématique client sans devoir tout coder en dur

  7. #7
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Concernant la fonction sleep, elle rend bien la main au scheduler qui lui va redonner la main au thread principal et donc au traitement des messages de la VCL non ?

    J'ai écrit mon propre compilateur de script qui génère un byte code qui est ensuite interprété (le byte code se résume en instructions simples comme Jump, mov, push, pop etc..) j'avais commencé le développement il y a 20 ans et je n'ai pas cessé de le faire évoluer. L'avantage est que j'en ai la parfaite maitrise , qu'il ne demande que très peu de ressources à l’exécution, qu'il est non bloquant et est très rapide d’exécution.
    Concernant l’accès aux propriétés de mes composants, tout passe par deux fonctions qui sont SetRealProp et SetStringProp qui permettent de modifier n'importe quelle propriété de composant de type string ou autre.
    Je vais voir si je peux passer par la fonction Synchronize pour appeller ces fonctions.

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 665
    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 665
    Points : 25 462
    Points
    25 462
    Par défaut
    Citation Envoyé par franckcl Voir le message
    Concernant la fonction sleep, elle rend bien la main au scheduler qui lui va redonner la main au thread principal et donc au traitement des messages de la VCL non ?
    Le scheduler, l'ordonnanceur du processeur peut passer d'un thread à un autre, et effectivement comme tu fais un sleep explicite, cela laisse plus de temps aux autres threads de s'executer dont le thread principal et la boucle de message !
    Mais même sans un sleep, windows passera la main de temps au temps aux autres thread !
    Surtout sur un multi-core, ton thread va prendre 100% d'un core (cela donne un total d'utilisation de 50% sur double, 25 sur un quad...) et les autres cores peuvent faire tourner les autres thread de ton processus ou des autres processus !
    Tu amalgames plusieurs notions disjointes !

    Citation Envoyé par franckcl Voir le message
    L'avantage est que j'en ai la parfaite maitrise
    Donc je ne vois pas le problème, tu as un donc un niveau de programmation suffisant qui te permettra de développer un système d'objet proxy qui émulera dans le script des objets qui nécessite de la synchronisation, c'est juste un travail nécessaire si tu veux faire un mélange de TThread et de TForm


    Citation Envoyé par franckcl Voir le message
    Concernant l’accès aux propriétés de mes composants, tout passe par deux fonctions qui sont SetRealProp et SetStringProp qui permettent de modifier n'importe quelle propriété de composant de type string ou autre.
    ??? TypInfo ? SetStrProp et SetFloatProp ?

    Au lieu de faire un appel direct tu mets en place le proxy comme cela

    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
    procedure TScriptEngine.SetStrProp(Instance: TObject; const PropName: string; const Value: string)
    begin
      // un filtre TControl protègera TForm, TButton ...
      // tu peux descendre au TComponent pour les TTable, TDataSource ...
      if (Instance is TControl) and (MainThreadID <> GetCurrentThreadId()) then
      begin
        FSyncContext.SetStrPropParams.Instance = Instance;
        FSyncContext.SetStrPropParams.PropName = PropName;
        FSyncContext.SetStrPropParams.Value = Value;
        Synchronize(SetStrPropSync());
      end
      else
        TypInfo.SetStrProp(Instance, PropName, Value); // Accès direct pour les autres objets TPersistent, quoi qu'un objet comme TFont devrait être synchronisé aussi, à toi de voir si tout est sync qui du coup rend l'utilisation de thread un peu discutable
    end;
     
    procedure TScriptEngine.SetStrPropSync();
    begin
      TypInfo.SetStrProp(
        FSyncContext.SetStrPropParams.Instance,
        FSyncContext.SetStrPropParams.PropName,
        FSyncContext.SetStrPropParams.Value
      );
    end;
     
    // dans ton thread ou un objet du moteur, tu as un membre privé FSyncContext
     
    type 
      TSyncContextSetStrPropParams = record
        Instance: TObject; 
        PropName: string; 
        Value: string;
      end;
     
      TSyncContextSetFloatPropParams = record
        Instance: TObject; 
        PropName: string; 
        Value: Extended;
      end;
     
      TSyncContext = record 
        case Integer of
          0 :(SetStrPropParams: TSyncContextSetStrPropParams);
          1 :(SetFloatPropParams: TSyncContextSetFloatPropParams);
      end;
    Dans tes scripts, il n'y a évidemment aucune différence, c'est juste ton implémentation qui change

  9. #9
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Ok j'ai bien tout compris ton code.
    Je vais mettre ça en application.
    MERCI !!

  10. #10
    Membre averti Avatar de franckcl
    Homme Profil pro
    Developpeur Delphi
    Inscrit en
    Septembre 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Developpeur Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Septembre 2004
    Messages : 516
    Points : 443
    Points
    443
    Par défaut
    Ca y est, j'ai pu mettre en place le "synchronize" et ça marche. Plus de problème d'affichage.
    Merci.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 13/05/2008, 09h53
  2. Réponses: 1
    Dernier message: 18/03/2008, 15h29
  3. STL list : acceder aux enfant d'une class depuis un liste
    Par poussinphp dans le forum SL & STL
    Réponses: 6
    Dernier message: 29/04/2007, 17h21
  4. Réponses: 4
    Dernier message: 11/10/2006, 10h56
  5. [css] acceder aux propriétés d'un autre objet
    Par bakonu dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 21/10/2005, 12h28

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