View Issue Details

IDProjectCategoryView StatusLast Update
0004817JEDI VCL00 JVCL Componentspublic2009-07-03 17:23
ReporterZENsanAssigned Toobones 
PrioritynormalSeveritytweakReproducibilityalways
Status resolvedResolutionfixed 
Product VersionDaily / GIT 
Target VersionFixed in Version3.38 
Summary0004817: TJVTimer incompatibility with TTimer
DescriptionIf JvTimer.Threaded then there is followinf situation:

JvTimer.Enabled := True;
...some time smaller than Interval...
JvTimer.Enabled := False; //UpdateTimer procedure MUST reset CurrectDuration
//so that after we set Enabled to True again, timer will execute event only after Interval miliseconds after we set it to Enabled, not after left miliseconds interval... like now.
Additional InformationSuggested fix for JvTimer.pas:

...
type
  TJvTimerThread = class(TThread)
  private
    FOwner: TJvTimer;
    FInterval: Cardinal;
    FException: Exception;
    FPaused: Boolean;
    FPauseSection: TCriticalSection;
    FCurrentDuration: Cardinal; //<-this required for updateTimer
    procedure HandleException;
    procedure SetPaused(const Value: Boolean);
    function GetPaused: Boolean;
  protected
    procedure Execute; override;
  public
    constructor Create(Timer: TJvTimer; Enabled: Boolean);
    destructor Destroy; override;
    {$IFDEF CLR}
    procedure Synchronize(Method: TThreadMethod); // makes method public
    {$ENDIF CLR}
    property Terminated;

    property Paused: Boolean read GetPaused write SetPaused;
  end;
...
procedure TJvTimerThread.Execute;
const
  Step = 10; // Time of a wait slot, in milliseconds
var
  EventTime: TJvTimerEventTime;

  function ThreadClosed: Boolean;
  begin
    Result := Terminated or Application.Terminated or (FOwner = nil);
  end;

begin
  repeat
    EventTime := FOwner.EventTime;

    if EventTime = tetPost then
    begin
      { Wait first and then trigger the event }
      FCurrentDuration := 0;
      while not ThreadClosed and (FCurrentDuration < FInterval) do
      begin
        SleepEx(Step, False);
        Inc(FCurrentDuration, Step);
      end;
    end;

    if not ThreadClosed and not ThreadClosed and FOwner.FEnabled then
    begin
      if FOwner.SyncEvent then
      begin
        Synchronize(FOwner.Timer)
      end
      else
      begin
        try
          FOwner.Timer;
        except
          on E: Exception do
          begin
            FException := E;
            HandleException;
          end;
        end;
      end;
    end;

    if EventTime = tetPre then
    begin
      { Wait after the event was triggered }
      FCurrentDuration := 0;
      while not ThreadClosed and (FCurrentDuration < FInterval) do
      begin
        SleepEx(Step, False);
        Inc(FCurrentDuration, Step);
      end;
    end;

    // while we are paused, we do not do anything. However, we do call SleepEx
    // in the alertable state to avoid 100% CPU usage. Note that the delay
    // should not be 0 as it may lead to 100% CPU in that case. 10 is a safe
    // value that is small enough not to have a big impact on restart.
    while Paused and not Terminated do
      SleepEx(10, True);
  until Terminated;
end;
...
procedure TJvTimer.UpdateTimer;
begin
  if FThreaded then
  begin
    FreeAndNil(FTimer);
    (FTimerThread as TJvTimerThread).Paused := True;
    (FTimerThread as TJvTimerThread).FCurrentDuration := 0;
{ if not FTimerThread.Suspended then
      FTimerThread.Suspend;}
    TJvTimerThread(FTimerThread).FInterval := FInterval;
    if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then
    begin
      FTimerThread.Priority := FThreadPriority;

      (FTimerThread as TJvTimerThread).Paused := False;
(* while FTimerThread.Suspended do
        FTimerThread.Resume;*)
    end;
  end
  else
  begin
    if not FTimerThread.Suspended then
      FTimerThread.Suspend;
    if not Assigned(FTimer) then
      FTimer := TTimer.Create(Self);
    FTimer.Interval := FInterval;
    FTimer.OnTimer := FOnTimer;
    FTimer.Enabled := (FInterval <> 0) and FEnabled and Assigned(FOnTimer);
  end;
end;
TagsNo tags attached.

Activities

obones

2009-07-03 17:23

administrator   ~0015760

This is now in SVN

Issue History

Date Modified Username Field Change
2009-06-10 16:41 ZENsan New Issue
2009-07-03 17:23 obones Note Added: 0015760
2009-07-03 17:23 obones Status new => resolved
2009-07-03 17:23 obones Fixed in Version => Daily / SVN
2009-07-03 17:23 obones Resolution open => fixed
2009-07-03 17:23 obones Assigned To => obones