Question:

Question:
I have an interface-based timer (see code below). Is it safe to use it like this?

var
ATimer : ITimer;

ATimer := TTimer.Create(100);
ATimer.Start(procedure
begin
// Do something
ATimer.Stop;
ATimer := nil; // This will destroy the timer object. Bad idea?
end;)

It works well but I suspect it is not safe.

==========================================

ITimer = interface(IInvokable)
['{1C06BCF6-1C6D-473E-993F-2B231B17D4F5}']
function Start(const Action: TProc): ITimer;
function Stop: ITimer;
end;

{ ITimer implementation }
type
TTimer = class(TInterfacedObject, ITimer)
private var
FTimer: VCL.ExtCtrls.TTimer;
FAction: TProc;
private
procedure RunAction(Sender: TObject);
public
constructor Create(const Interval: Cardinal);
destructor Destroy; override;
class function New(const Interval: Cardinal): ITimer;
function Start(const Action: TProc): ITimer;
function Stop: ITimer;
end;


{ TTimer }

constructor TTimer.Create(const Interval: Cardinal);
begin
FTimer := VCL.ExtCtrls.TTimer.Create(nil);
FTimer.Enabled := False;
FTimer.Interval := Interval;
FTimer.OnTimer := RunAction;
end;

destructor TTimer.Destroy;
begin
FTimer.Free;
inherited;
end;

class function TTimer.New(const Interval: Cardinal): ITimer;
begin
Result := Create(Interval);
end;

procedure TTimer.RunAction(Sender: TObject);
begin
FAction;
end;

function TTimer.Start(const Action: TProc): ITimer;
begin
Result := Self;
FAction := Action;
FTimer.Enabled := True;
end;

function TTimer.Stop: ITimer;
begin
Result := Self;
FTimer.Enabled := False;
end;

(code from https://github.com/nunopicado/Reusable-Objects)


https://github.com/nunopicado/Reusable-Objects

Comments

  1. I don't have time now to dig into this but one more thing to be aware is that your anonymous method will not start when you call ATimer.Start().
    If you create the timer for example at the button click the anonymous procedure will start only at the end of the button event and not at the ATimer.Start().

    ReplyDelete
  2. Now I understand.
    If you call Application.ProcessMessages after ATimer.Start() your timer will start at this point.

    ReplyDelete
  3. Cristian Peța while at the same time causing all sorts of reentrancy issues for code not expecting to be called twice in the same message stack.

    ReplyDelete

Post a Comment