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 :

Question TThread et wrAbandoned


Sujet :

Composants VCL Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 527
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 527
    Par défaut Question TThread et wrAbandoned
    Bonjour

    Extrait de l'aide Delphi :
    wrAbandoned
    L'objet événement a été détruit avant l'écoulement de la période TimeOut.
    De ce que je comprend, l'objet évènement c'est le TEvent que j'utilise.
    Donc, si je le détruis, je devrais passer dans le cas wrAbandoned.

    Code de test que je pensais être correct mais qui plante !

    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
     
    unit Unit9;
     
    interface
     
    uses
      Winapi.Windows, Winapi.Messages,
      System.SysUtils, System.Variants, System.Classes, System.SyncObjs,
      Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
     
    type
      TForm9 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        Evt: TEvent;
        procedure OnThreadTerminate(Sender: TObject);
      end;
     
      TMonThread = class(TThread)
      private
        Evt: TEvent;
        FP : TProc<string>;
      public
        constructor Create(P: TProc<string>; FEvt: TEvent); overload;
        procedure Execute; override;
      end;
     
    var
      Form9: TForm9;
     
    implementation
     
    {$R *.dfm}
     
     
    procedure TForm9.Button1Click(Sender: TObject);
    var
      T: TMonThread;
    begin
      Evt := TEvent.Create(nil, True, false, 'truc');
      T   := TMonThread.Create(
        procedure(S: string)
        begin
          Caption := S;
        end,
        Evt);
      T.OnTerminate := Self.OnThreadTerminate;
      T.Start;
    end;
     
    { TMonThread }
     
    constructor TMonThread.Create(P: TProc<string>; FEvt: TEvent);
    begin
      inherited Create(True);
      FreeOnTerminate := True;
      FP              := P;
      Evt             := FEvt;
    end;
     
    procedure TMonThread.Execute;
    var
      I: Integer;
    begin
      I := 50;
      while not terminated do
      begin
        FP(TimeToStr(Now));
        case Evt.WaitFor(1000) of
          wrSignaled:
            begin
              FP('Signalé');
              Terminate;
            end;
          wrTimeout:
            Dec(I);
          wrAbandoned:
            begin
              FP('Abandonné');
              Terminate;
            end;
        end;
        if I = 0 then
          Terminate;
      end;
    end;
     
    procedure TForm9.Button2Click(Sender: TObject);
    begin
      // Test pour wrAbandoned
      Evt.Free;
     
      Exit;
     
      // Signaler pour terminer
      Evt.SetEvent;
    end;
     
    procedure TForm9.OnThreadTerminate(Sender: TObject);
    begin
      if Evt <> nil then
        Evt.Free;
    end;
     
    end.
    Je démarre le thread, tout se passe bien.
    Dès que je clique sur le bouton 2,

    ---------------------------
    Notification des exceptions du débogueur
    ---------------------------
    Le projet LesThreads.exe a déclenché la classe d'exception $C0000005 avec le message 'access violation at 0x00004164: read of address 0x00004164'.
    ---------------------------
    Arrêter Continuer Aide
    ---------------------------
    puis

    ---------------------------
    Notification des exceptions du débogueur
    ---------------------------
    Le projet LesThreads.exe a déclenché la classe d'exception EInvalidPointer avec le message 'Opération de pointeur incorrecte'.
    ---------------------------
    Arrêter Continuer Aide
    ---------------------------

    Question : Le cas wrAbandoned il est déclenché comment ?

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 999
    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 : 13 999
    Par défaut
    Libération de Evt deux fois, peut-être même trois fois dont deux dans OnThreadTerminate

    déjà, on va en supprimer une

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TForm9.OnThreadTerminate(Sender: TObject);
    begin
      FreeAndNil(Evt);
    end;
    et la seconde

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TForm9.Button2Click(Sender: TObject);
    begin
      // Test pour wrAbandoned
      FreeAndNil(Free);
     
      Exit;
     
      // Signaler pour terminer
      Evt.SetEvent;
    end;
    Attention Evt est modifié pour TForm9 mais TMonThread possède toujours une référence, potentiellement libérée, ne supporte pas l'utiliser

    Enfin wrAbandoned, on a déjà débattu dans arrêter un TEVent qui ne concerne que TMutex et non TEvent


    Pour moi, Evt ne devrait pas être connu de l'extérieur de TMonThread, l'échange de TEvent en paramètre entre Form et TMonThread, à ne pas faire !

    Tu dois ajouter des encapsulations pour faire le SetEvent par exemple un TMonThread.Pulse() ou typiquement en cas de FIFO un TMonThread.Add(Item), une fois l'Item ajouté à la ThreadList ou Queue, appelle de SetEvent pour pop les items un par un


    Dans ton cas, utilise TerminatedSet pour déclencher le SetEvent, d'ailleurs pas besoin de Terminate dans la boucle du TMonThread
    C'est tout l'inverse

    Form appele TMonThread.Terminate(), la redéfinition de TerminatedSet appel SetEvent

    bonne lecture de "TThread.Suspend et TThread.Resume deprecated " .. mais encore , tu as la totalement, la gestion de l'arrêt du thread mais en plus sa mise en pause au besoin
    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 Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2007
    Messages
    3 527
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 527
    Par défaut
    Pour moi, Evt ne devrait pas être connu de l'extérieur de TMonThread, l'échange de TEvent en paramètre entre Form et TMonThread, à ne pas faire !
    Tu veux dire que le TEvent est plus à sa place dans le Thread et qu'il faut le "piloter" à distance par l'intermédiaire d'une procédure ? Ok ! Ca se tient !

    TerminatedSet n'est pas expliqué dans la doc ! Le classique

    Embarcadero Technologies ne possède pas d'informations supplémentaires pour le moment. Veuillez nous aider à documenter cette rubrique en utilisant la page Discussion !

    Récupérée de « http://localhost/Libraries/XE7/f/ind...et&oldid=67026 »
    Toujours aussi plaisante cette phrase ...

    Mais ok, je prends exemple sur ton code

    Juste pour info, Le SetEvent pour terminer fonctionne avec le partage du TEvent mais j'admets que ce partage n'est pas si utile que ça.

Discussions similaires

  1. Question sur les TThreads
    Par Pypiou dans le forum C++Builder
    Réponses: 4
    Dernier message: 21/04/2014, 06h43
  2. Réponses: 4
    Dernier message: 22/06/2008, 11h00
  3. [TTHREAD] ne termine pas sont exécution
    Par Bbenj dans le forum Langage
    Réponses: 4
    Dernier message: 02/08/2002, 16h42
  4. Question de faisabilité
    Par lisarasu dans le forum CORBA
    Réponses: 3
    Dernier message: 14/05/2002, 11h26
  5. [HyperFile] 2 questions de débutant
    Par khan dans le forum HyperFileSQL
    Réponses: 2
    Dernier message: 29/04/2002, 23h18

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