How to start/stop a monitoring Delphi thread on demand?

前端 未结 3 1614
有刺的猬
有刺的猬 2021-01-01 08:11

I\'ve been looking for a way to monitor for specific registry changes in Delphi. Found a solution at about.com:

procedure TRegMonitorThread.Execute;
begin
           


        
相关标签:
3条回答
  • 2021-01-01 08:36

    This works, just make small changes as below and now when you call Terminate:

      TRegMonitorThread = class(TThread)
      ...
      public
        procedure Terminate; reintroduce;
    ...
    
    procedure TRegMonitorThread. Terminate;  // add new public procedure
    begin
      inherited Terminate;
      Windows.SetEvent(FEvent);
    end;
    
    procedure TRegMonitorThread.Execute;
    begin
      InitThread;
    
      while not Terminated do
      begin
        if WaitForSingleObject(FEvent, INFINITE) = WAIT_OBJECT_0 then
        begin
          if Terminated then // <- add this 2 lines
            Exit;
          ...
        end;
      end;
    end;
    
    0 讨论(0)
  • 2021-01-01 08:45

    Instead in INFINITE you should have WaitForSingleObject time out after a period. That way the loop continues and Terminated is checked.

    procedure TRegMonitorThread.Execute;
    begin
      InitThread; // method omitted here
      while not Terminated do
      begin
        if WaitForSingleObject(FEvent, 1000) = WAIT_OBJECT_0 then
        begin
          fChangeData.RootKey := RootKey;
          fChangeData.Key := Key;
          SendMessage(Wnd, WM_REGCHANGE, RootKey, LongInt(PChar(Key)));
          ResetEvent(FEvent);
    
          RegNotifyChangeKeyValue(FReg.CurrentKey, 1, Filter, FEvent, 1);
        end;
      end;
    end;
    

    The methods TThread.Suspend and TThread.Resume could theoretically be used to temporary stop threads, but as Delphi 2010 now acknowledges they are not safe for use. See TThread.resume is deprecated in Delphi-2010 what should be used in place? and http://msdn.microsoft.com/en-us/library/ms686345%28VS.85%29.aspx

    0 讨论(0)
  • 2021-01-01 08:49

    Use WaitForMultipleObjects() with an array of two events instead of WaitForSingleObject(). Add a manual reset event to the thread class, and signal it after you have set Terminated to True. Check the return value which of the two events has been signalled, and act accordingly.

    Edit:

    Some minimal Delphi 2009 code to demonstrate the idea. You have to add SyncObjs to the list of used units, and add

      fTerminateEvent: TEvent;
    

    to the private section of your thread class.

    constructor TTestThread.Create;
    begin
      inherited Create(TRUE);
      fTerminateEvent := TEvent.Create(nil, True, False, '');
      // ...
      Resume;
    end;
    
    destructor TTestThread.Destroy;
    begin
      fTerminateEvent.SetEvent;
      Terminate; // not necessary if you don't check Terminated in your code
      WaitFor;
      fTerminateEvent.Free;
      inherited;
    end;
    
    procedure TTestThread.Execute;
    var
      Handles: array[0..1] of THandle;
    begin
      Handles[0] := ...; // your event handle goes here
      Handles[1] := fTerminateEvent.Handle;
      while not Terminated do begin
        if WaitForMultipleObjects(2, @Handles[0], False, INFINITE) <> WAIT_OBJECT_0 then
          break;
        // ...
      end;
    end;
    

    You only need to add the code in your question to it. Simply trying to free the thread instance will do everything necessary to unblock the thread (if necessary).

    0 讨论(0)
提交回复
热议问题