Einzelnen Beitrag anzeigen

Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Thread + Timer, Einbinden von TimerThread.pas

  Alt 10. Sep 2014, 16:47
Jupp, dass nach dem Enabled := False noch einmal ExecuteTimed aufgerufen wird, liegt daran, dass ich vergessen habe im Setter von Enabled den Event auszulösen.

Habe ich jetzt mal geändert und zusätzlich dahingehend erweitert, dass der Event nur bei einer echten Änderung auslöst (Interval und Enabled ).

Ein kleiner Fehler war auch noch im Execute , da wurde der Wert LInterval nicht benutzt

Zur Verwendung: Am sinnvollsten ist es sich von dieser Klasse eine neue Klasse abzuleiten.
Delphi-Quellcode:
unit MyTimerThread;

interface

uses
  TimerThread;

type
  TMyTimerThread = class( TTimerThread )
  protected
    procedure ExecuteTimed; override;
  end;

implementation

procedure TMyTimerThread.ExecuteTimed;
begin
  // hier jetzt der eigene Code rein
end;

end.
Hier die korrigierte Version der Unit:
Delphi-Quellcode:
unit TimerThread;

interface

uses
  System.Classes,
  System.SyncObjs;

const
  TIMERTHREAD_INTERVAL_DEFAULT = 1000;
  TIMERTHREAD_ENABLED_DEFAULT = True;

type
  TTimerThread = class( TThread )
  private
    FCS : TCriticalSection;
    FEvent : TEvent;
    FInterval : Cardinal;
    FEnabled : Boolean;
    procedure SetInterval( const Value : Cardinal );
    function GetInterval : Cardinal;
    procedure SetEnabled( const Value : Boolean );
    function GetEnabled : Boolean;
  protected
    procedure Execute; override; final;
    procedure ExecuteTimed; virtual;
    // ACHTUNG! Das gibt es erst ab Delphi XE2
    procedure TerminatedSet; override;
  public
    constructor Create;
    destructor Destroy; override;

    property Interval : Cardinal read GetInterval write SetInterval default TIMERTHREAD_INTERVAL_DEFAULT;
    property Enabled : Boolean read GetEnabled write SetEnabled default TIMERTHREAD_ENABLED_DEFAULT;
  end;

implementation

{ TTimerThread }

constructor TTimerThread.Create;
begin
  FCS := TCriticalSection.Create;
  FEvent := TEvent.Create( nil, False, False, '' );
  inherited Create( False );
  FInterval := TIMERTHREAD_INTERVAL_DEFAULT;
  FEnabled := TIMERTHREAD_ENABLED_DEFAULT;
end;

destructor TTimerThread.Destroy;
begin

  inherited;
  FEvent.Free;
  FCS.Free;
end;

procedure TTimerThread.Execute;
var
  LInterval : Cardinal;
begin
  inherited;
  while not Terminated do
    begin
      if Enabled then
        LInterval := Interval
      else
        LInterval := INFINITE;

      if FEvent.WaitFor( LInterval ) = TWaitResult.wrTimeout
      then
        ExecuteTimed;
    end;
end;

procedure TTimerThread.ExecuteTimed;
begin

end;

function TTimerThread.GetEnabled : Boolean;
begin
  FCS.Enter;
  try
    Result := FEnabled;
  finally
    FCS.Leave;
  end;
end;

function TTimerThread.GetInterval : Cardinal;
begin
  FCS.Enter;
  try
    Result := FInterval;
  finally
    FCS.Leave;
  end;
end;

procedure TTimerThread.SetEnabled( const Value : Boolean );
begin
  FCS.Enter;
  try
    if Value <> FEnabled then
    begin
      FEnabled := Value;
      FEvent.SetEvent;
    end;
  finally
    FCS.Leave;
  end;
end;

procedure TTimerThread.SetInterval( const Value : Cardinal );
begin
  FCS.Enter;
  try
    if Value <> FInterval then
    begin
      FInterval := Value;
      FEvent.SetEvent;
    end;
  finally
    FCS.Leave;
  end;
end;

procedure TTimerThread.TerminatedSet;
begin
  inherited;
  FEvent.SetEvent;
end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (11. Sep 2014 um 08:07 Uhr)
  Mit Zitat antworten Zitat