AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Schlafende Threads

Ein Thema von shmia · begonnen am 11. Mai 2012 · letzter Beitrag vom 15. Mai 2012
Antwort Antwort
brechi

Registriert seit: 30. Jan 2004
823 Beiträge
 
#1

AW: Schlafende Threads

  Alt 11. Mai 2012, 21:24
Irgendwie gefällt mir das auch alles nicht, wieso z.b. das ResetEvent vor DoWork? Ausserdem wird as FEvent zu spaet erzeugt.

wie wärs mit:

Delphi-Quellcode:

type
  TSleepingThread = class(TThread)
  protected
    FEvent: TEvent;
    FBusy: Boolean;
    procedure Execute; override;
    procedure DoWork; virtual; abstract;
  public
    function WakeUp: Boolean;
    constructor Create(_Suspended: Boolean);
    destructor Destroy; override;
    property Busy: Boolean read FBusy;
  end;

  TTestThread = class(TSleepingThread)
  private
    FCountLoop: Integer;
  protected
    procedure DoWork; override;
    property CountLoop: Integer read FCountLoop;
  end;

{ TMyThread }

constructor TSleepingThread.Create(_Suspended: Boolean);
begin
  FEvent := TEvent.Create(nil, True, False, '');
  FBusy := False;
  inherited Create(_Suspended);
end;

destructor TSleepingThread.Destroy;
begin
  Terminate; // FTerminate setzen
  WakeUp; // Event setzen
  WaitFor; // warten bis der eigene Thered sich beendet hat
  FreeAndNil(FEvent);
  inherited;
end;

function TSleepingThread.WakeUp: Boolean;
begin
  Result := FBusy;
  if not Result then
    FEvent.SetEvent;
end;

procedure TSleepingThread.Execute;
begin
  while not Terminated do begin
    case FEvent.WaitFor(INFINITE) of
      wrSignaled: begin
          if not Terminated then begin
            FBusy := True;
            DoWork;
            FEvent.ResetEvent;
            FBusy := False;
          end;
        end;
      wrTimeout: ;

      wrError: begin
          ReturnValue := FEvent.LastError;
          Exit;
        end;

      wrAbandoned:
        Exit;
    end;
  end;
end;

{ TTestThread }

procedure TTestThread.DoWork;
var
  t: Cardinal;
begin
  t := GetTickCount;
  while GetTickCount - t < 2000 do
    Sleep(100);
  Inc(FCountLoop);
end;

procedure TForm28.OnTerminateThread(_Sender: Tobject);
begin
  caption := inttostr((_Sender as TTestThread).CountLoop);
end;

procedure TForm28.Button1Click(Sender: TObject);

var
  tt: TTestThread;
begin
// recht sinnloses beispiel da FreeAndNil immer auf Ende wartet aller arbeiten wartet
// und es somit "blockierend" aussieht
  tt := TTestThread.Create(False);
  try
    tt.OnTerminate := OnTerminateThread;
    if tt.WakeUp then begin
      // joa konnte ausgefuerht werden
    end;
    Sleep(10); // naja irgendwas im HauptThread zwischendurch
  finally
    FreeAndNil(tt);
  end;
end;
Edit: Ah Thread falsch aufgeweckt ;P
Edit2: Beispiel erweiter (u.a. busy usw.)

Geändert von brechi (11. Mai 2012 um 21:40 Uhr) Grund: erweitert
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#2

AW: Schlafende Threads

  Alt 14. Mai 2012, 09:21
Hi brechi,

Das Terminate in den Destructor zu setzen gefällt mir auch.

Aber den geerebten Constructor kannst du auch am Anfang aufrufen. Das ist ein Märchen, dass bei TThread das inherited am Ende des Constructors sitzen muss. Der Thread wird eh erst in der überschriebenen Methode "AfterConstruction" gestartet (sofern createsuspended=false), also erst wenn der komplette Code des Constructors abgearbeitet ist.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#3

AW: Schlafende Threads

  Alt 14. Mai 2012, 17:19
Der Thread wird eh erst in der überschriebenen Methode "AfterConstruction" gestartet (sofern createsuspended=false), also erst wenn der komplette Code des Constructors abgearbeitet ist.
Für Delphi 5 scheint das aber nicht zu stimmen:
Delphi-Quellcode:
constructor TThread.Create(CreateSuspended: Boolean);
var
  Flags: DWORD;
begin
  inherited Create;
  AddThread;
  FSuspended := CreateSuspended;
  Flags := 0;
  if CreateSuspended then Flags := CREATE_SUSPENDED;
  FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), Flags, FThreadID); // <=====
end;
Also muss man wohl zuerst das Event erzeugen (oder man erzeugt es erst in Execute() und handelt sich dafür andere Probleme ein).

Irgendwie gefällt mir das auch alles nicht, wieso z.b. das ResetEvent vor DoWork?
Weil ja während DoWork noch abgearbeitet wird von Aussen ein neuer "WakeUp-Befehl" eintreffen könnte.
So richtig nützlich wird das Ganze erst, wenn man noch ein threadsicheren Fifo hinzunimmt, damit DoWork jedes Mal die richtigen Inputdaten bekommt.

Aber es scheint ja auch so schon schwierig genug einen TThread mit einem TSimpleEvent zu verheiraten.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.336 Beiträge
 
Delphi 12 Athens
 
#4

AW: Schlafende Threads

  Alt 14. Mai 2012, 17:35
Jetzt weiß ich auch wieder, warum ich nur noch die Kompatibilität bis D7 und bei aktuellen Projekten nur noch bis maximal D2006 gewährleiste
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#5

AW: Schlafende Threads

  Alt 14. Mai 2012, 18:00
Für Delphi 5 scheint das aber nicht zu stimmen:
Daher kommt das immer. Ok in Delphi 7 wird im Constructor BeginThread immer CREATE_SUSPENDED aufgerufen und dann gibt es AfterConstruction:
Delphi-Quellcode:
procedure TThread.AfterConstruction;
begin
  if not FCreateSuspended then
    Resume;
end;
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#6

AW: Schlafende Threads

  Alt 15. Mai 2012, 17:43
Ich habe den Konstruktor jetzt so geändert:
Delphi-Quellcode:
constructor TSleepingThread.Create(CreateSuspended: Boolean);
begin
   inherited Create(True);
   FEvent := TSimpleEvent.Create;
   if not CreateSuspended then
      Resume;
end;
Ausserdem gibt es noch einen 2. Thread in dem Demo um es einfache Datenübergabe zu zeigen.
Andreas
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:27 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz