大悟还俗

邮箱 key_ok@qq.com 我的收集 http://pan.baidu.com/share/home?uk=1177427271
posts - 236, comments - 8, trackbacks - 0, articles - 0
  新随笔  :: 联系 :: 订阅 订阅  :: 管理

线程【四】线程内定时器

Posted on 2013-10-09 13:02 大悟还俗 阅读(...) 评论(...) 编辑 收藏

在消息队列部分,我们已经知道消息泵是以线程为单位进行分离的!

换句话说,有N个程序,都产生了相关事件,在系统消息队列中会根据线程来区分,当线程的消息泵从系统消息队列抽取消息时,会挑属于自己线程的消息。

当我们创建一个工程时,IDE环境已经为我们生成了主线程的代码以及消息泵,而当我们自己创建一个Worker线程时,默认是没有消息泵的,如果想要在线程内接收消息,需要添加消息泵!

消息泵的结构:

while  GetMessage(Msg,  0 ,  0 ,  0 )  do   begin   

   TranslateMessage(Msg);  

   DispatchMessage(Msg)  

 end ; 

另:

要想在线程内响应消息,没有窗口是不行的

所以要在线程中创建窗口(AllocateHWND)(分配窗口的工作在VCL中的Timer控件中已经完成),来使之有接收消息(WM_TIMER)的能力!

注意:在线程内创建TIMER时应该在线程函数中创建!在构造函数中创建控件的话会窗口创建至主线程中!

(TThread.Execute本身就是对API的线程函数的封装,这个地方看一下VCL封装的线程类即可)

 

 

unit Unit2;
interface
uses
  Classes,ExtCtrls,dialogs,Windows;
type
  TMyTest = class(TThread)
  private
    FTimer:TTimer;
    procedure TimerProc(Sender: TObject);
  protected
    procedure Execute; override;
  public
    constructor create;
    destructor Destroy; override;
  end;
implementation
constructor TMyTest.Create;
begin
  Inherited Create(true);
end;
destructor TMyTest.Destroy;
begin
  inherited;
end;
procedure TMyTest.Execute;
var
  Msg: TMsg;
begin
   FTimer:=TTimer.Create(nil);//一定要在线程函数中创建,如果在线程的构造函数中创建,就把窗口创建到主线程中了,那线程中的TIMER肯定不会接收WM_TIMER消息。
   try
     FTimer.Enabled:=True;
     FTimer.Interval:=5000 ;
     FTimer.OnTimer:=TimerProc;
     while GetMessage(Msg, 0, 0, 0) do begin
        TranslateMessage(Msg);
        DispatchMessage(Msg)
      end;
      Terminate;
   finally
     FTimer.Free;
   end;
  { Place thread code here }
end;
procedure TMyTest.TimerProc(Sender: TObject);
begin
   //业务处理
end;
View Code