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 :

Problème avec TList et Threads


Sujet :

Composants VCL Delphi

  1. #1
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 13
    Points : 7
    Points
    7
    Par défaut Problème avec TList et Threads
    Bonjour tous le monde,

    J'ai un petit soucis j'essaye de faire un programme qui teste une liste d'ips qu'on lui charge depuis un fichier texte pour qu'il fasse differents tests dessus.

    Pour avoir une gestion dynamique des threads et pour que l'utilisateur puisse choisir sur combien de threads testes etc ... j'ai utilise une TList mais j'ai un soucis lors de la creation du thread une exception est soulevee.

    Unit1.pas
    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
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons;
     
    type
      TForm1 = class(TForm)
        BitBtn1: TBitBtn;
        ListBox1: TListBox;
        BitBtn2: TBitBtn;
        procedure BitBtn1Click(Sender: TObject);
        procedure BitBtn2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    uses
       Unit2;
     
    Type
       PTestThread = ^TTestThread;
     
    Var
       IpToTest   : TStringList;
       ThreadList : TList;
       TestThread : PTestThread;
       MaxThreads : Integer;
       i          : Integer;
     
    {$R *.dfm}
     
    procedure TForm1.BitBtn1Click(Sender: TObject);
    begin
       i := 0;
     
       while i < IpToTest.count do
       begin
          if ThreadList.count <= MaxThreads then
          begin
             new(TestThread);
             TestThread^.create(true);
             TestThread^.FreeOnTerminate := true;
             TestThread^.resume;
             ThreadList.add(TestThread);
             inc(i);
          end;
       end;
    end;
     
    procedure TForm1.BitBtn2Click(Sender: TObject);
    var
       openDialog : TOpenDialog;
    begin
       openDialog := TOpenDialog.Create(self);
       try
          openDialog.InitialDir := GetCurrentDir;
          openDialog.Options := [ofFileMustExist];
          openDialog.Filter := 'Tous les fichiers|*.*';
          openDialog.FilterIndex := 2;
          if openDialog.Execute then begin
             IpToTest.LoadFromFile(openDialog.FileName);
             ListBox1.Items.LoadFromFile(openDialog.FileName);
          end;
       finally
          openDialog.Free;
       end;
    end;
     
    Initialization
       IpToTest := TStringList.Create;
       ThreadList := TList.Create;
     
    Finalization
       IpToTest.Free;
       ThreadList.Free;
     
    end.
    Unit2.pas
    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
    unit Unit2;
     
    interface
     
    uses
      Classes;
     
    type
      TTestThread = class(TThread)
      private
        { Private declarations }
      protected
        procedure Execute; override;
      end;
     
    implementation
     
    { Important: Methods and properties of objects in visual components can only be
      used in a method called using Synchronize, for example,
     
          Synchronize(UpdateCaption);
     
      and UpdateCaption could look like,
     
        procedure TTestThread.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end; }
     
    { TTestThread }
     
    procedure TTestThread.Execute;
    begin
      { Place thread code here }
    end;
     
    end.
    Je suis sur (quasi) que le probleme vient des pointeurs, si qqn peut m'eclairer je lui en serait tres reconnaissant, merci

    P.S : desole pour la poncutatiom j'utilise un clavier qwerty

  2. #2
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2002
    Messages
    1 288
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2002
    Messages : 1 288
    Points : 1 936
    Points
    1 936
    Par défaut
    Pourquoi utiliser un pointeur?

    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
     
    var
      Form1: TForm1;
     
    implementation
     
    uses
       Unit2;
     
    Var
       IpToTest   : TStringList;
       ThreadList : TList;
       TestThread : TTestThread;
       MaxThreads : Integer;
       i          : Integer;
     
    {$R *.dfm}
     
    procedure TForm1.BitBtn1Click(Sender: TObject);
    begin
       i := 0;
     
       while i < IpToTest.count do
       begin
          if ThreadList.count <= MaxThreads then
          begin
             TestThread := TTestThread.Create;
             TestThread.FreeOnTerminate := True;
             TestThread.Resume;
             ThreadList.add(TestThread);
             inc(i);
          end;
       end;
    end;
     
    procedure TForm1.BitBtn2Click(Sender: TObject);
    var
       openDialog : TOpenDialog;
    begin
       openDialog := TOpenDialog.Create(self);
       try
          openDialog.InitialDir := GetCurrentDir;
          openDialog.Options := [ofFileMustExist];
          openDialog.Filter := 'Tous les fichiers|*.*';
          openDialog.FilterIndex := 2;
          if openDialog.Execute then begin
             IpToTest.LoadFromFile(openDialog.FileName);
             ListBox1.Items.LoadFromFile(openDialog.FileName);
          end;
       finally
          openDialog.Free;
       end;
    end;
     
    Initialization
       IpToTest := TStringList.Create;
       ThreadList := TList.Create;
     
    Finalization
       IpToTest.Free;
       ThreadList.Free;
     
    end.
    Par contre une TList ne libère pas ses objets quand elle est détuite, contrairement à une TObjectList
    Delphi 7/XE2/XE3
    C#
    Oracle 9i à 12c
    SQL Server 2008 à 2014

  3. #3
    Futur Membre du Club
    Inscrit en
    Août 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 13
    Points : 7
    Points
    7
    Par défaut
    Merci pour les indication enfaite j'utilise les pointeurs car les Tlists ont comme elements aue des pointeurs non ?

    Normalement a la fin la Tlist est vide donc l4utilisation d'une TList est suffisante

  4. #4
    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
    Je pense avoir compris ton problème: tu crées la classe de ton thread comme un pointeur (avec New).
    Comme te l'as montré Linkin, il faut créer ta classe de cette façon:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TestThread := TTestThread.Create;
    Du coup, tu as le choix entre rester à la Tlist, ou bien passer à la TObjectList qui peut "owner" les objets qu'elles contient: elle les libère lors de sa destruction.
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

  5. #5
    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
    Attention, vouloir un ensemble TThread via une TObjetList , cela semble périlleux ... surtout avec l'option FreeOnTerminate activé, qui peut rendre l'objet TThread caduque à n'importe quel moment ...

    Sinon, je rappèle qu'un objet c'est un pointeur déguisé ... et qu'un TObjectList n'est qu'une TList typé TObject avec OwnsObjects comme option parfois sympathique

    Citation Envoyé par Linkin
    Par contre une TList ne libère pas ses objets quand elle est détuite, contrairement à une TObjectList
    heureusement car avec FreeOnTerminate, bonjour les dégats ...
    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

  6. #6
    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
    Citation Envoyé par ShaiLeTroll Voir le message
    Attention, vouloir un ensemble TThread via une TObjetList , cela semble périlleux ... surtout avec l'option FreeOnTerminate activé, qui peut rendre l'objet TThread caduque à n'importe quel moment ...
    Sauf si on spécifie OwnsObject à false lors de la création de la TObjectList
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

  7. #7
    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
    Dans ce cas, je ne vois presque aucun intérêt à utiliser une TObjectList, car il faudra toujours caster un TObject en TThread, ce qui ne change rien de caster un Pointer en TThread ...

    Ensuite, conserver les Thread en FreeOnTerminate à true, c'est s'exposé à des violations d'accès sur un thread qui a terminé son execution, ... et si l'on veut gérer leur arrêt, vaut mieux FreeOnTerminate à false, et faire soit même Terminate, WaitFor et Free ...

    sinon pour éclairer necralbert, ton erreur est simplement une méconnaissance de l'objet

    la forme est toujours

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Instance := Class.Create();
    ce que tu as bien fait pour IpToTest

    Ensuite, même si avec des objets, le passage par pointeur n'est pas utile, il est bon de rapperl Chaque New doit avoir son Dispose, par exemple faire sa propre List comme ceci pour typé fortement sa liste est simplifier son utilisation

    dans l'exemple qui suit, TModeleType peut être une chaine, un entier, une structure.

    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
    unit uModeleTypeList;
     
    interface
     
    uses Classes;
     
    type
      TModeleType = Double; // A Titre d'Exemple ...
      PModeleType = ^TModeleType;
     
      TModeleTypeList = class(TList)
      protected
        function GetItem(const Index: Integer): TModeleType;
        procedure SetItem(const Index: Integer; const Value: TModeleType);
      public
        function Add(const AModeleType: TModeleType): Integer;
        procedure Clear; override;
        procedure Delete(const Index: Integer);
        procedure Insert(const Index: Integer; const AModeleType: TModeleType);
        function First: TModeleType;
        function Last: TModeleType;
        // Propriétés
        property Items[const Index: Integer]: TModeleType read GetItem write SetItem; default;
      end;
     
     
    implementation
     
    // TModeleTypeList ---------------------------------------------------------------
    //                                                                           -
    //                    TModeleTypeList - Protected                                -
    //                                                                           -
    // TModeleTypeList ---------------------------------------------------------------
     
    // TModeleTypeList - Protected ---------------------------------------------------
    function TModeleTypeList.GetItem(const Index: Integer): TModeleType;
    begin
         // On veut une Structure ModeleType, et n'ont pas un pointeur, donc déférencement (^)
         Result := PModeleType(inherited Items[Index])^;
    end;
     
    // TModeleTypeList - Protected ---------------------------------------------------
    procedure TModeleTypeList.SetItem(const Index: Integer; const Value: TModeleType);
    begin
         // On veut une Structure ModeleType, et n'ont pas un pointeur, donc déférencement (^)
         PModeleType(inherited Items[Index])^ := Value;
    end;
     
    // TModeleTypeList ---------------------------------------------------------------
    //                                                                           -
    //                     TModeleTypeList - Public                                  -
    //                                                                           -
    // TModeleTypeList ---------------------------------------------------------------
     
    // TModeleTypeList - Public ------------------------------------------------------
    function TModeleTypeList.Add(const AModeleType: TModeleType): Integer;
    var
       TmpModeleType: PModeleType;
    begin
         New(TmpModeleType);
         TmpModeleType^ := AModeleType;
         Result := inherited Add(TmpModeleType);
    end;
     
    // TModeleTypeList - Public ------------------------------------------------------
    procedure TModeleTypeList.Clear;
    var
       Index: Integer;
    begin
         for Index := Count - 1 downto 0 do begin
             if Assigned(inherited Items[Index]) then begin
                Dispose(PModeleType(inherited Items[Index]));
             end;
         end;
     
         inherited Clear();
    end;
     
    // TModeleTypeList - Public ------------------------------------------------------
    procedure TModeleTypeList.Delete(const Index: Integer);
    begin
         Dispose(PModeleType(inherited Items[Index]));
     
         inherited Delete(Index);
    end;
     
    // TModeleTypeList - Public ------------------------------------------------------
    procedure TModeleTypeList.Insert(const Index: Integer; const AModeleType: TModeleType);
    var
       TmpModeleType: PModeleType;
    begin
         New(TmpModeleType);
         TmpModeleType^ := AModeleType;
         inherited Insert(Index, TmpModeleType);
    end;
     
    // TModeleTypeList - Public ------------------------------------------------------
    function TModeleTypeList.First: TModeleType;
    begin
         // On veut un ModeleType, et n'ont pas un pointeur, donc déférencement (^)
         Result := PModeleType(inherited First())^;
    end;
     
    // TModeleTypeList - Public ------------------------------------------------------
    function TModeleTypeList.Last: TModeleType;
    begin
         // On veut un ModeleType, et n'ont pas un pointeur, donc déférencement (^)
         Result := PModeleType(inherited Last())^;
    end;
     
    end.
    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

Discussions similaires

  1. Problème avec les multi-threads
    Par Dominique49 dans le forum Général Java
    Réponses: 5
    Dernier message: 12/12/2011, 15h20
  2. Réponses: 4
    Dernier message: 18/10/2009, 18h36
  3. Problème avec un Timer/Thread
    Par Mede12 dans le forum Général Java
    Réponses: 4
    Dernier message: 30/07/2009, 09h23
  4. [SFML] Problème avec affichage en thread
    Par black is beautiful dans le forum SFML
    Réponses: 0
    Dernier message: 05/05/2009, 10h33
  5. Problème avec repaint() et Thread.sleep
    Par fab13 dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 12/08/2008, 23h02

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