首页  编辑  

线程Timer对象

Tags: /超级猛料/Thread.线程/   Date Created:

线程Timer对象

type

 TTimerThread = class ;

 TWakeupKind = ( wkTimerExpired , wkEventTriggered );

 TWaitState = ( wsIdle , wsWaiting );

 TWakeupEvent = procedure ( sender : TTimerThread ; reason : TWakeupKind ) of object ;

 TTimerThread = class ( TThread )

  private

   FInterval : DWORD ;

   FReason : TWakeupKind ;

   FEvent : THandle ;

   FState : TwaitState ;

   FWakeupEvent : TWakeupEvent ;

   FNoWakeupEvent : Boolean ;

    procedure SyncWakeup ;

  protected

    procedure DoWakeup ;

  public

    constructor Create ; reintroduce ;

    destructor Destroy ; override ;

    procedure Execute ; override ;

    procedure Sleep ( forInterval : DWORD );

    procedure Wakeup ;

    procedure Terminate ;

    property OnTimer : TWakeupEvent read FWakeupEvent write FWakeupEvent ;

    property Interval : DWORD read FInterval write FInterval ;

    property State : TWaitState read FState ;

  end ; {TTimerThread}

implementation

{ TTimerThread }

constructor TTimerThread . Create ;

begin

  // create thread suspended

  inherited Create ( true );

  // create event object

 FEvent := CreateEvent (

    nil , // use default security

   true , // event will be manually reset

   false , // event starts out not signaled

    nil ); // event has no name

  if FEvent = 0 then

    raise Exception . CreateFmt ( 'TTimerThread.Create: could not create API event handle.'#13#10'%s' ,

      [ Syserrormessage ( GetLastError )]);

  // thread will stay suspended until started by a Sleep or Resume call

 FState := wsIdle ;

 FNoWakeupEvent := False ;

end ;

destructor TTimerThread . Destroy ;

begin

  inherited ;

  if FEvent <> 0 then

   CloseHandle ( FEvent );

end ;

procedure TTimerThread . DoWakeup ;

begin

  // called in threads context to fire OnWakeup event

  if Assigned ( FWakeupEvent ) and not FNoWakeupEvent then

   Synchronize ( SyncWakeup );

end ;

procedure TTimerThread . Execute ;

var

 res : DWORD ;

begin

  // Executes inside threads context

  repeat

   Fstate := wsWaiting ;

   res := WaitForSingleObject ( FEvent , FInterval );

    if res = WAIT_OBJECT_0 then

    begin

     FReason := wkEventTriggered ;

     ResetEvent ( FEvent );

    end

    else

     FReason := wkTimerExpired ;

   DoWakeup ;

    if not Terminated then

    begin

     Fstate := wsIdle ;

     Suspend ;

    end ;

  until Terminated ;

end ;

procedure TTimerThread . Sleep ( forInterval : DWORD );

begin

  // called from outside threads context to start thread sleeping

 Interval := forInterval ;

  if State <> wsIdle then

  begin

    // thread is already waiting. Wake it up but disable wakeup event

   FNoWakeupEvent := true ;

    try

     Wakeup ;

      while State = wsWaiting do

       Windows . Sleep ( 10 );

    finally

     FNoWakeupEvent := false ;

    end ;

  end ;

 Resume ;

end ;

procedure TTimerThread . SyncWakeup ;

begin

  // executes in main threads context

  // Note: FWakeupevent has already been checked to be <> nil in DoWakeup

 FWakeupEvent ( self , FReason );

end ;

procedure TTimerThread . Terminate ;

begin

  inherited Terminate ;

  // in case thread is waiting, don't fire Wakeup event on wakeup.

 FNoWakeupEvent := true ;

 Wakeup ;

end ;

procedure TTimerThread . Wakeup ;

begin

  // executes in callers thread context

  if State = wsWaiting then

   SetEvent ( FEvent );

end ;