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 :

[TThread] Question conception : ajout méthode publique à un Thread


Sujet :

API, COM et SDKs Delphi

  1. #1
    Membre éclairé
    Homme Profil pro
    Freelance
    Inscrit en
    Décembre 2003
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Décembre 2003
    Messages : 423
    Par défaut [TThread] Question conception : ajout méthode publique à un Thread
    Message Original : (voir fin de ce post pour ré-expression de la question )

    (Re)Bonsoir à tous,

    Je travaille actuellement sur une application manipulant entre autres un GPS et des caméras.
    Pour des raisons de performances, je compte créer cette application en multi-thread.

    Seulement, il y a une partie où je ne vois pas trop comment je vais m'y prendre (pour le moment je réfléchie beaucoup à comment créer tout ça ... j'essaie d'anticiper sur les soucis).
    En fait je compte créer un thread par caméra utilisé (cela n'excèdera pas 4 caméras ... et encore ... ). Ce thread aura différent buts :
    1) créer mon objet caméra
    2) Prendre des photos à partir de la caméra
    3) effectuer divers traitements sur les images récupérées (permettant ainsi de régler à nouveau la caméra pour les prises de photos futures)

    Comme je viens de le dire, je compte dans chaque thread instancier un objet de type caméra (pas de problème particulier ?) permettant ainsi de manipuler mes caméras (physiques) plus facilement.
    Seulement, depuis ma fenêtre principale, l'utilisateur devrait pouvoir modifier certaines propriétés de mes caméras (à l'intérieur de mes threads).

    Je tiens à préciser que JAMAIS le thread ne sera en cours d'exécution lors d'une modification des paramètres de mes caméras (un appel à suspend aura été fait forcément avant).
    Je pensais alors ajouté à ma classe TThreadCamera par exemple, une méthode ModifierParametreCamera par exemple permettant de modifier les paramètres de ma caméra.


    Est-ce possible ? Est-ce correcte ? Comment auriez-vous fait vous autrement ?


    Il est fort probable que vous n'ayez pas tout compris à où je veux en venir, ce qui est tout à fait normal, une application multitache étant rarement évidente et qui plus est ici je ne facilite pas les choses. Auquel cas, n'hésitez pas à me le faire remarquer, on essaiera de se comprendre.



    Pour terminer, voila grosso modo ce que je pense faire ... est-ce quelque chose de viable ? (ne tenez pas compte de la non prise en charge des sections critiques etc ... c'est juste pour que vous voyez à peu près ce que je veux faire) :

    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
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
     
    Unit UPrinc;
    ...
    interface
    ...
        TFormPrinc = class(TForm)
            // Quelques composants ...
            private
            // quelques variables/méthodes
            protected
            // quelques variables/méthodes
            public
            // quelques variables/méthodes
            end;
     
    var
        FormPrinc: TFormPrinc;
     
    implementation
    ...
    procedure TFormPrinc.ClickLanceCamera(...);
    begin
        if threadCamera1=nil then
            threadCamera1 = TThreadCamera.Create(...)
        else
            threadCamera.Resume;
    end;
     
    ...
     
    procedure TFormPrinc.ClickStopCamera(...)
    begin
        if threadCamera1<>nil then threadCamera1.Suspend;
    end;
     
    ...
     
    procedure TFormPrinc.ClickCalibrerCamera(...)
    var donnees: TReglagesCamera;    
    begin
        donnees := LancerFenetreReglage(); // Juste histoire de dire que par exemple on
        // exécute une nouvelle fiche et qu'on récupère les nouveaux réglages de la caméra
        threadCamera1.AppliquerReglages(donnees); // est-ce vraiment bien de faire ça ?
    end;
     
    ...
     
    end.
     
     
     
     
     
     
    unit UThreadCamera;
     
    ...
     
    interface
     
    ...
        TCamera = class;
     
        TThreadCamera = class(TThread)
            private
                camera: TCamera;
            protected
                Constructor Create(...);
                procedure Execute; override;
            public
                procedure AppliquerReglages(donnees: TReglagesCamera);
        end;
     
        TCamera = class
            private
                fUnParametre: integer;
                fUnAutreParametre: string;
                ...
            protected
                ...
            public
                ...
        end;
     
    implementation
     
    ...
    constructor TThreadCamera.Create(...):
    begin
        camera := TCamera.Create(...);
        FreeonTerminate := false;
        ...
        inherited Create(...);
    end;
     
    ...
     
    procedure TThreadCamera.Execute;
    begin
        ... // manipulation de l'objet camera et traitement des photos prises
    end;
     
    procedure TThreadCamera.AppliquerReglages(...)
    begin
        if Suspended then camera.AppliquerReglages(...);
    end;
    ...
     
    constructor TCamera.Create(...);
    begin
        ...
    end;
     
    end.
    A la rigueur peut-être même il n'est pas nécessaire que le thread soit suspendu ... une simple protection sur les paramètres de la caméra et c'est bon ... Enfin ça c'est une autre histoire ...



    Merci de m'avoir lu,
    et merci à quiconque pourra m'aider ...

    -----------------------------

    Modification :

    Je me rends compte que c'est pas forcément évident à lire le bout de code que j'ai fourni. Donc ej vais essayer de résumer ma question ainsi :
    Soit une classe dérivé de TThread.
    Est-il correct d'ajouter une méthode public à cette classe qui pourrait alors être appelée par le thread principal ? Conceptuellement est-ce que ça se fait ? (mon but étant de modifier des paramètres d'exécution du Thread secondaire par exemple).


    Par avance merci

  2. #2
    Membre Expert

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Par défaut
    Personnellement, j'éviterais de créer des méthodes publiques au thread qui seraient appelées depuis un autre thread car ça risque d'être trompeur d'un point de vu sémantique :
    Lorsqu'on fait un objet, on définit une entité autonome. Les méthodes de manipulation de l'objet ont pour but d'encapsuler le code et les traitements dans une même entité : Ce n'est pas du code externe qui modifie les attributs de l'objet c'est l'objet qui se modifie lui même par l'intermédiaire de ses méthodes.

    Si tu définis des méthodes publiques sur le thread, lorsque tu appelles cette méthode, on a tendance à penser que c'est le thread appelé qui fait la modification.
    Hors l'exécution de la méthode s'effectue bel et bien dans le contexte du thread qui effectue l'appel. C'est donc un autre thread qui vient modifier le thread appelé.

    En ce sens, je pense que ça risque de prêter à confusion. Il serait à la rigueur préférable de créer des propriétés sur le thread secondaires pour modifier des informations qui seront ensuitent comprises et traitées par ce dernier.

    Bien entendu, tout ceci n'est que purement conceptuel, d'un point de vu technique ça peut se faire.


    Par contre, j'aurais quelques questions par rapport à l'architecture générale :
    Tu comptes utiliser quel type de caméra ? des caméras USB ou des caméras classiques, branchées sur une carte d'acquisition ? Dans ce dernier cas, est-ce que tu vas utiliser une carte par caméra ou une carte d'acquisition unique avec les entrées multiplexées ?

    Si tu te trouves dans le dernier cas de figure (remarque c'est peut-être pareil dans les autres cas) tu ne pourras de toute façon prendre qu'une seule photo à la fois.
    Donc je ne suis pas sûr que l'architecture un thread par caméra soit une bonne idée.
    Je verai plutôt la chose sous la forme, un thread pour faire l'acquisition vidéo et prendre une photo sur une caméra. Ce thread sera chargé de contrôler la carte d'acquisition et de prendre les photos, puis lorsqu'une photo a été prise, il la transmet à un autre thread qui traite la photo et l'analyse. Ensuite, il ne reste plus qu'à ajouter un troisième pour gérer l'IHM et afficher les resultats (tiens je viens de décrire DirectShow).
    Si tu veux également piloter des caméras (Réglage du Zoom, mise au point, orientation) tu peux également ajouter un thread pour effectuer ces réglages.
    Du temps où je faisais ce genre de chose, les réglages de la caméras se commandaient via une lisaison RS, tandis que la vidéo arrivait sur un signal composite. Donc on pouvait parfaitement continuer à prendre des photos tout en modifiant le réglage des caméras.

  3. #3
    Membre éclairé
    Homme Profil pro
    Freelance
    Inscrit en
    Décembre 2003
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Décembre 2003
    Messages : 423
    Par défaut
    Tout d'abord, merci de m'avoir répondu,

    Ensuite pour te répondre :

    Entre le moment où j'ai posté le message et aujourd'hui j'ai nécessairement eu le temps de penser à un peu tout ça. D'abord pour te répondre, il s'agit en fait de caméra branchés sur une prise firewire. Chaque caméra à sa prise mais le tout sur une unique carte. Donc en fait c'est vrai, j'ai peut-être abusé dans le terme "simultanément". Nécessairement, compte tenu de l'architecture, toutes les caméras ne peuvent pas prendre la photo en même temps (où alors arrêtez moi tout de suite). J'entendais par simultanément : les unes après les autres le plus vite possible en gros ...

    Vis à vis de l'architecture que tu me conseilles, j'en suis aussi personnellement arrivé à quelque chose de plus ou moins similaire. La voici, dis moi ce que tu en penses :

    Le Main thread => gèrerait en gros l'IHM (permettrait d'arrêter la prise de photo, demander des modifications de réglages etc. A ce propos, on est bien d'accord, c'est à la classe caméra elle même de contenir ses propres méthodes de modification. En fait quand je parlais de méthode publique dans un thread c'était juste histoire d'appeler ensuite une méthode de la caméra qu'il contient celle-ci étant, dans mon idée, uniquement connue par le thread qui la contient ).
    Un trhead par caméra => lancés par Main trhead. Il créerait une caméra (donc un trhead par caméra). Sa procédure exécute serait de prendre une photo (à une condition, dépendante d'un autre matériel, mais là n'est pas le problème)
    Un thread Gestion Carte ou Distribution image => lancé par Main thread. Son but est simple : initialiser correctement la carte (ou pas d'ailleurs) mais surtout son execute serait d'attendre qu'une image voyage sur le bus. Une fois celle-ci prête, il sait alors de quelle caméra elle vient => il appelle une méthode de la caméra correspondante : TraiterPhoto
    Cette fameuse méthode lancerait alors un thread (un resume pas un create ... il aura été créé automatiquement en même temps que la caméra mais immédiatement suspendu). Son execute serait une méthode de ma caméra qui se chargerait de traiter ma photo. Une fois le traitement terminé, le thread s'auto suspendrait ...


    J'espère avoir été assez clair ... Qu'en penses-tu ?

    On voit là alors où interviendrait mes méthodes publiques de thread : lors de l'appel du lancement de TraiterPhoto de la classe Camera depuis le thread de gestion des images ... Ou encore, dans le Main thread lorsque via une fenêtre on appuie sur réglage ... Ces méthodes serait donc des accesseurs ...


    Par avance, merci pour tout aide ...

  4. #4
    Membre Expert

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Leader Technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Par défaut
    Je ne sais pas ce que tu fais comme traitement d'image, mais faire ce traitement dans le même objet que la camera ne me semble pas être une bonne idée.
    Par la suite, tu seras peut-être ammené à travailler avec d'autres caméras, qui prendront leur photo différemment, qui se commanderont différemment.
    En revanche, le travaille d'analyse de la photo sera certainement le même quel que soit la caméra qui l'a prise.

    Donc tu as plutôt intérêt à séparer les deux dans deux objets distincts. Le jour où tu dois travailler avec d'autres caméras, tu fais une autre classe caméra et tu l'instancies à la place de la première, tout en gardant le code d'analyse de l'image dans sa classe d'origine...

    Ensuite, ta façon de parler du multi-threading me perturbe un peu. Tu sembles partir du principe qu'il faut créer des threads pour exécuter une méthode, puis lorsque le traitement est terminé, que c'est un autre thread qui suspend/active le thread qui travaille.

    En principe, on met en place une architecture multi-threadée pour recupérer les temps d'attentes imposés par un traitement et s'en servir pour faire autre chose.
    Dans cette optique, on travaille plutôt selon le principe suivant :
    - Tu as un thread qui prend des photos. L'acquisition d'une photo prend un certain temps (le travail est fait par la carte). Lorsque la photo est prise, le thread qui fait les acquisitions la dépose dans un file d'attente.
    - Un deuxième thread est chargé de traiter la photo. Ce dernier se met en attente de reception d'une photo sur la file. La file d'attente étant un objet de synchro géré par windows, lorsque la file est vide, le thread est automatiquement suspendu par windows (la tâche est en attente d'un événement). Dès qu'une image arrive dans la file, windows réveille le thread. Ce dernier récupère la photo, fait son traitement et place le résultat dans une autre file (ou positionne un sémaphore...) pour signaler la fin du traitement. Puis il se remet en attente d'une photo à traiter dans la file (ce qui a pour effet de le suspendre si la file est vide).

    De cette façon, les threads s'activent et se désactivent automatiquement, sans que tu n'ais à t'en préoccuper.
    J'ai lu tes autres posts sur le suspend immédiat/différé d'un thread, à la fin d'une boucle.
    Pour moi, tu essaies de résoudre des problèmes qui n'ont pas lieu d'être.

  5. #5
    Membre éclairé
    Homme Profil pro
    Freelance
    Inscrit en
    Décembre 2003
    Messages
    423
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Freelance

    Informations forums :
    Inscription : Décembre 2003
    Messages : 423
    Par défaut
    Tout d'abord merci encore de ta réponse,


    En fait, je pense qu'on parle plus ou moins de la même architecture seulement premièrement j'ai du mal à exprimer comment je le concoit dans ma tête, et deuxièmement j'ai volontairement omis un certain nombre de prédicats qui font que je dois gérer les threads un peu bizarrement. Donc essayons d'y aller étape par étape.
    Je ne sais pas ce que tu fais comme traitement d'image, mais faire ce traitement dans le même objet que la camera ne me semble pas être une bonne idée.
    Par la suite, tu seras peut-être ammené à travailler avec d'autres caméras, qui prendront leur photo différemment, qui se commanderont différemment.
    En revanche, le travaille d'analyse de la photo sera certainement le même quel que soit la caméra qui l'a prise.

    Donc tu as plutôt intérêt à séparer les deux dans deux objets distincts. Le jour où tu dois travailler avec d'autres caméras, tu fais une autre classe caméra et tu l'instancies à la place de la première, tout en gardant le code d'analyse de l'image dans sa classe d'origine...
    Je vois très bien ce que tu veux dire et où tu veux en venir ... Effectivement c'est plein de bon sens. C'est un peu comme ça que je voyais la chose ... en réalité pas au début, seulement en commençant le développement je me suis dit "m@#$de là ça va coincer si je fais ça comme ça" ... j'y ai donc réfléchi un petit moment pour finalement me rapprocher de ce que tu dis. Entre l'idée que j'en avais et ce que tu viens de dire, je pense que je devrais pouvoir m'en sortir à ce niveau.

    Ensuite, ta façon de parler du multi-threading me perturbe un peu. Tu sembles partir du principe qu'il faut créer des threads pour exécuter une méthode, puis lorsque le traitement est terminé, que c'est un autre thread qui suspend/active le thread qui travaille.
    Non ne t'inquiète pas je ne le conçois pas comme ça

    En principe, on met en place une architecture multi-threadée pour recupérer les temps d'attentes imposés par un traitement et s'en servir pour faire autre chose.
    Dans cette optique, on travaille plutôt selon le principe suivant :
    - Tu as un thread qui prend des photos.
    Je suis d'accord pour le principe du multitache, et concernant ce thread je l'ai y'a pas de soucis.

    L'acquisition d'une photo prend un certain temps (le travail est fait par la carte). Lorsque la photo est prise, le thread qui fait les acquisitions la dépose dans un file d'attente.
    En fait c'est à partir de là que ça ne peut pas réellement fonctionner comme ça ... Je m'explique : comme je l'ai dit au début, j'ai omis un certain nombre d'hypothèse quand au projet et dont une assez importante : pour la prise de photo, les envois de nouveaux paramètres à la caméra PHYSIQUE etc. je m'appuie sur une DLL pré-existante. Et donc quand je prends une photo, elle se met en fait dans le buffer de cette DLL. Pour la récupérer, il me faut faire appel à deux autres fonction de la DLL qui peuvent prendre un certain temps (le temps de voyage sur le bus en fait) ... Donc au final, quand je prends ma photo j'appelle une fonction de ma DLL elle me renvoie true ou false et c'est tout.

    Ainsi avant de passer au deuxième thread dont tu parles, j'en crée donc un qui est là pour appeler la fonction de la DLL permettant de récupérer la photo. En gros son code est le suivant :

    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
     
    procedure execute;
    var num: integer;
    begin
         while not(Terminated) do
         begin
              num := AttendrePhoto(TEMPS_ATTENTE);
              if (num <> -1) then
              begin
                  // num contient le numéro de la caméra correspondant à celle qui a pris la photo qui vient de transiter ...
                  // je dois donc ensuite récupérer la photo et faire un traitement dessus.
              end
              else
                  // J'ai rien a faire, si ce n'est recommencer ... donc un petit sleep histoire de pas non plus occuper le proco non stop ... sauf si pas nécessaire ???
         end;
    end;
    Un deuxième thread est chargé de traiter la photo. Ce dernier se met en attente de reception d'une photo sur la file.
    Ok, donc ça fait un troisième thread, sauf que vu les contraintes que j'ai je me dis que c'est à moi de dire vas-y lance toi une photo est prête pour toi( un par caméra du coup) ...
    ...
    Sauf que là en écrivant ça je me rends compte que là c'est pas normal ... et du coup je vois parfaitement où tu veux en venir ...
    En fait il faudrait que pour le thread précédent son traitement soit simplement par exemple d'ajouter une info dans une B.A.L. et le dernier thread fonctionnerait exactement comme tu le décris : bloque sur une boite et attend ...
    Une question alors (une de plus ) : est-ce que comme sous Linux, il existe le principe de boite au lettre à identifiant unique mais "compartimenté" ?




    Au final si on essaie de résumer :
    J'ai un thread (par caméra) chargé de prendre des photos. A chaque photo prise, j'enregistre trois valeurs (heure, distance, vitesse)
    J'ai un thread chargé d'attendre qu'une photo ait voyagé sur le BUS de ma carte : une fois arrivée le rôle de ce thread est d'ajouter à une BAL "quelque chose d'un certain type" pour qu'un autre thread comprenne qu'il doit lancer son traitement.
    J'ai un autre thread (par caméra) chargé de lire la BAL en attente de "quelque chose d'un type précis" permettant alors de traiter la photo (indépendamment de l'objet caméra ça on est d'accord).


    De cette façon, les threads s'activent et se désactivent automatiquement, sans que tu n'ais à t'en préoccuper.
    De cette façon on est d'accord


    J'ai lu tes autres posts sur le suspend immédiat/différé d'un thread, à la fin d'une boucle.
    Pour moi, tu essaies de résoudre des problèmes qui n'ont pas lieu d'être.
    En fait ça c'est juste que l'utilisateur a la possibilité de lancer le programme, mais que la caméra ne soit pas en acquisition : il a donc un bouton stop on va dire. Je voudrais que l'appui sur ce bouton ne bloque pas un thread en plein milieu du traitement de l'image par exemple. Je veux être sûr qu'avant d'être arrêter il ait fini son traitement COMPLETEMENT ... voila pourquoi je cherche à faire ce que tu as appelé (à juste titre ) suspend différé



    Quoiqu'il en soit merci énormément pour ta forte contribution à ce sujet ... Lundi matin je me poserais et essaierais de formaliser ceci et je te retiendrais au courant ...


    Encore merci pour tout

Discussions similaires

  1. [Conception] Ajouter des "0" devant un nombre
    Par xender dans le forum PHP & Base de données
    Réponses: 11
    Dernier message: 18/01/2012, 16h19
  2. Question sur les méthodes abstraites
    Par nmathon dans le forum Delphi
    Réponses: 3
    Dernier message: 15/06/2006, 20h30
  3. Ajouter un programme comme thread (?)
    Par sloshy dans le forum Windows
    Réponses: 5
    Dernier message: 22/02/2006, 10h07
  4. Question sur les LinkedList et les threads
    Par berg dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 10/09/2005, 19h16
  5. [WebServices][axis] question sur la méthode service()
    Par Nycos62 dans le forum Services Web
    Réponses: 9
    Dernier message: 21/04/2005, 09h32

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