让Delphi TTimer与多线程应用程序配合使用

时间:2012-05-14 19:22:00

标签: multithreading delphi timer vcl omnithreadlibrary

我遇到一个问题,一个简单的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事件正确分配等等...

我正在使用Delphi 2010

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

1 个答案:

答案 0 :(得分:7)

TTimer是基于消息的计时器。无论创建TTimer的线程上下文是什么,都必须有一个活动的消息循环,以便TTimer处理其WM_TIMER消息。

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

如果您需要线程安全计时器,请直接调用CreateWindow()并直接泵送/处理WM_TIMER消息,或者使用不同的计时器机制,例如通过{{的线程多媒体计时器1}},甚至只是通过timeSetEvent()Sleep()的简单忙碌循环。在不知道您使用计时器的情况下,很难确定适合您需求的替代方案。