Search code examples
delphitimer

What changes are needed to get this timer to work under Delphi Alexandria 64 bit?


The violation occurs at the line "Suspended" in the callback. The timer component is the SVATimer.pas that I've used for years with good, accurate results. It does still run under Rio, but not Alexandria.

procedure MMTimerCallBack(TimerID, Msg: Uint; dwUser, dw1, dw2: DWORD); stdcall;
begin
  with TSVATimerThread(dwUser) do
    if Suspended then begin
      TimeKillEvent(FTimerID);
      FTimerID:= 0
    end
    else
      Synchronize(FOwner.DoTimerProc)
end;

procedure TSVATimerThread.Execute;
begin
  repeat
    FTimerID:= TimeSetEvent(FInterval, 0, @MMTimerCallBack, cardinal(Self), TIME_PERIODIC);
    if FTimerID <> 0 then    
      WaitForSingleObject(FEvent, INFINITE);
    if FTimerID <> 0 then
      TimeKillEvent(FTimerID)
  until Terminated
end;

Solution

  • A pointer is a 32-bit value in a 32-bit build, and a 64-bit value in a 64-bit build. However, you are passing around your Self pointer as a 32-bit value regardless of the build type, so it gets truncated in a 64-bit build.

    You need to fix your declaration of MMTimerCallBack() and the call to TimeSetEvent(), per the documentation, so that you are passing the pointer correctly in both build types, eg:

    procedure MMTimerCallBack(TimerID, Msg: UINT; dwUser, dw1, dw2: DWORD_PTR); stdcall;
    begin
      ...
    end;
    
    procedure TSVATimerThread.Execute;
    begin
      ...
      FTimerID := TimeSetEvent(..., @MMTimerCallBack, DWORD_PTR(Self), ...);
      ...
    end;