Avatar billede rozh Nybegynder
20. august 2007 - 00:27 Der er 10 kommentarer og
1 løsning

Tjekke "Terminated" på aktuel tråd

Hej

Jeg har flere tråde som kalder den samme procedure. Noget i stil med:

T1, T2: TThread

T1.Execute
begin
  DoSomeThing;
end;

T2.Execute
begin
  DoSomeThing;
end;

procedure DoSomeThing;
begin
  repeat
    SomeThing
  until "calling thread is terminated"
 
end;

Problemet er at jeg ikke ved hvordan man tjekker for om den tråd man er i, er Terminated. Jeg ved jo ikke hvilken tråd har kaldt min procedure.

Spørgsmålet går ud på hvordan jeg finder den tråd som har kaldt min procedure DoSomeThing (altså den aktive tråd) inde fra selve proceduren mens den kører

Jeg vil helst undgå at skulle sende pointere og variable ol. med til proceduren.

VH
Avatar billede arne_v Ekspert
20. august 2007 - 01:35 #1
Hvis en tråd er ved at checke om den selv er termineret, så er den vel per definition
ikke termineret ??
Avatar billede rozh Nybegynder
20. august 2007 - 08:51 #2
Terminated er en boolean der indikerer at der har været en forespørgesel om tråd afslutning. Når man kalder T1.Terminate (det vil man gør feks hvis program vil lukke ned, men vil vente til alle tråde er frigivet) så sættes terminated til True. Men hvis tråden er ved at køre en loop og ikke tjekker for om terminated er true, så får man bare et program der ikke svarer. Dvs et kald til Terminate afslutter ikke tråden med vold og magt, men blotter sætter et flag.
Avatar billede hrc Mester
20. august 2007 - 09:39 #3
TThread har en OnTerminate. Den kan du hægte på dit hovedprogram som så kan administrere en en liste over aktive tråde eller bare en trådtæller.
Avatar billede kroning Nybegynder
20. august 2007 - 11:11 #4
Det "normale" er vel at have en enkelt variabel Sender: TObject, og så er dit problem jo løst.

procedure DoSomeThing(Sender: TObject);
begin
  repeat
    SomeThing
  until "calling thread is terminated"
end;
Avatar billede rozh Nybegynder
20. august 2007 - 16:38 #5
Hej

Det er gode forslag i kommer med here. Og jeg bruger lige nu noget der ligner det kroning skriver (jeg har en pointer som referere til terminated variablen, istedet for hele objektet, men er vel stortset det samme). Så jeg kan godt komme rundt om problemet.

Men selvom man kan løse problemet på mange måder, synes jeg det ville se bedst ud hvis man kunne finde ud hvilken tråd man kørte. Og det er også af "æstetiske" grunde jeg skrev, at jeg helst vil undgå pointere mm.

Jeg ved at der i delphi er functionerne GetCurrentThreadID og GetCurrentThread. Kan man bruge dem til at finde det aktuelle tråd ?

VH
Avatar billede kroning Nybegynder
20. august 2007 - 18:26 #6
Lige en lille ting, (Sender: TObject) er også kun en pointer.
Avatar billede hrc Mester
20. august 2007 - 22:09 #7
Jeg vil påstå et min løsning er den rigtige idet tråden selv fyrer eventen af (med sender = self) når den dør. Der kan ikke blive meget lettere

unit FMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ContNrs, StdCtrls, ComCtrls;

type
  TTestThread = class(TThread)
  private
    fDieAt : TDateTime;
  public
    constructor Create(const aLiveForNSecords : integer); reintroduce;
    procedure Execute; override;
  end;

  TfrmMain = class(TForm)
    btnStart: TButton;
    sbMain: TStatusBar;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ThreadTerminate(Sender: TObject);
    procedure btnStartClick(Sender: TObject);
  private
    fThreadList : TObjectList;
  public
  end;

var
  frmMain: TfrmMain;

implementation

uses
  DateUtils;

{$R *.dfm}

procedure TfrmMain.btnStartClick(Sender: TObject);
var
  TestThread : TTestThread;
begin
  TestThread := TTestThread.Create(random(20) + 5);
  TestThread.OnTerminate := ThreadTerminate;
  TestThread.Resume;
  fThreadList.Add(TestThread);
  sbMain.Panels[0].Text := format('Antal tråde: %d',[fThreadList.Count]);
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  fThreadList := TObjectList.Create(false);
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  fThreadList.Free;
end;

procedure TfrmMain.ThreadTerminate(Sender: TObject);
begin
  fThreadList.Extract(Sender);
  sbMain.Panels[0].Text := format('Antal tråde: %d',[fThreadList.Count]);
end;

{ TTestThread }

constructor TTestThread.Create(const aLiveForNSecords: integer);
begin
  inherited Create(true);
  FreeOnTerminate := true;
  fDieAt := IncSecond(now, aLiveForNSecords);
end;

procedure TTestThread.Execute;
var
  DontDie : boolean;
begin
  inherited;
  DontDie := true;
  while DontDie do
  begin
    DontDie := fDieAt > now;
    if DontDie then
      sleep(0);
  end;
end;

end.
Avatar billede hrc Mester
20. august 2007 - 22:16 #8
Har du brug for en anden Event at sende retur laver du bare den:

  TTestThread = class(TThread)
  private
    fDieAt : TDateTime;
    fNotifyEvent : TNotifyEvent;
  public
    constructor Create(const aLiveForNSecords : integer); reintroduce;
    procedure Execute; override;
    property OnNotify : TNotifyEvent read fNotifyEvent write fOnNotifyEvent;
  end;


procedure TTestThread.Execute;
var
  DontDie : boolean;
begin
  inherited;
  DontDie := true;
  while DontDie do
  begin
    if assigned(fNotifyEvent) then
      fNotifyEvent(self);
    DontDie := fDieAt > now;
    if DontDie then
      sleep(0);
  end;
end;
Avatar billede rozh Nybegynder
20. august 2007 - 22:23 #9
Hej hrc

Det du har er en tråd der er tidsindstillet til at dø. Og så har du en event der sørger for at opdatere formen med hvilke tråde der kører. Har jeg forstået det rigtigt ?

Men jeg kan ikke se hvorfra man i en sub-proceudre vil kunne se om den kaldende tråd er "død" eller "levende" ? (hvilket er det som jeg skal bruge)

Og desuden så har jeg ikke bruge for at tjekke tråden inde fra execute. Det skal være inde fra en sub-procedure (DoSomeThing proceduren i exemplet)

Og forresten er sbMain.Panels[0].Text trådsikker, eller bruger du en anden sync/mutex der ikke fremgår af koden ?
Avatar billede rozh Nybegynder
04. september 2007 - 19:53 #10
Jeg har desværre ikke fundet præcis det jeg ledte efter.

Men det er vel et udtryk for at det ikke kan lade sig gøre på den måde.

Alle deltagere må gerne smide et svar så deles I om pointene, da I forsøgte at hjælpe :-)
Avatar billede hrc Mester
16. oktober 2007 - 11:12 #11
Det kan godt være du skal pakke OnNotify ind i en Synchronize for at være sikker.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester