3

我有一个简单的 TTimer 问题,该 TTimer 已启动并在主应用程序线程中执行其 OnTimer 事件,代码如下所示:

procedure TForm1.DoSomeStuff();
begin
     OmniLock.Acquire;
     try
        Parallel.Pipeline.NumTasks(MaxThreads).Stage(StageProc).Run;

        if (MyTimer = nil) then
        begin
             MyTimer := TTimer.Create(nil);
             MyTimer.Interval := 60 * 1000;  // timer fired every 60 seconds
             MyTimer.OnTimer := MyTimerEvent;
             MyTimer.Enabled := True;
         end;
      finally
             OmniLock.Release;
      end;    // try/finally
 end;

当我在一个简单的项目/演示中执行代码时,一切正常,但在我的应用程序(使用 Omni Thread Library v3)中,计时器事件永远不会被触发

我很确定它什么都没有,我只是不知道出了什么问题!

我三重检查:MyTimer在我的代码中只分配一次,它的 OnTimer 事件被正确分配,等等......

我正在使用德尔福 2010

任何人都知道如何解决这个问题?

4

1 回答 1

7

TTimer是一个基于消息的计时器。无论在哪个线程上下文TTimer中创建,都必须有一个活动的消息循环才能TTimer处理其WM_TIMER消息。

TTimer不是线程安全的计时器。为了接收WM_TIMER消息,它必须HWND为自己分配一个窗口句柄。它使用 VCL 的AllocateHWnd()函数来执行此操作,该函数不是线程安全的,并且不能从主线程的上下文之外调用。

如果您需要一个线程安全的计时器,可以直接调用CreateWindow()并直接抽取/处理WM_TIMER消息,或者使用不同的计时器机制,例如通过 线程多媒体计时器timeSetEvent(),甚至只是通过Sleep()或的简单忙循环WaitForSingleObject()。在不知道您使用计时器的目的的情况下,很难找到适合您需求的替代方案。

于 2012-05-14T19:54:36.550 回答