【问题标题】:What changes are needed to get this timer to work under Delphi Alexandria 64 bit?需要做哪些更改才能使此计时器在 Delphi Alexandria 64 位下工作?
【发布时间】:2023-02-07 03:53:18
【问题描述】:

违规发生在回调中的“Suspended”行。计时器组件是 SVATimer.pas,我已经使用了多年,结果非常准确。它仍然在里约热内卢,但不是亚历山大港。

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;

【问题讨论】:

  • (1) Cardinal(Self)必须是NativeInt(Self)。 (2) dwUser, dw1, dw2必须是DWORD_PTR。请注意,此代码具有绝不在 64 位上是正确的。它只是偶然起作用的。本质上,这个 Q 是 stackoverflow.com/a/74508271/282848 的副本。另外,请注意,如果您阅读the documentation,您本可以自己解决所有这些问题。
  • 我很抱歉显得如此无知。似乎有很多我不知道的。谢谢,这些改变奏效了。
  • @AndreasRejbrand“Cardinal(Self) 必须是 NativeInt(Self)" - 实际上,它应该是 DWORD_PTR(Self) 以匹配 API。

标签: delphi timer


【解决方案1】:

您将 Self 指针作为 32 位值传递,因此它在 64 位构建中被截断。您需要修复 MMTimerCallBack() 的声明和对 TimeSetEvent() 的调用以正确传递指针,例如:

procedure MMTimerCallBack(TimerID, Msg: UINT; dwUser, dw1, dw2: DWORD_PTR); stdcall;
begin
  ...
end;

procedure TSVATimerThread.Execute;
begin
  ...
  FTimerID := TimeSetEvent(..., @MMTimerCallBack, DWORD_PTR(Self), ...);
  ...
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-04
    • 2011-04-18
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    相关资源
    最近更新 更多