关于线程的停止、挂起、退出(修改)

原来的实现:http://blog.csdn.net/jankercsdn/article/details/8874469 有许多不完善的地方,使用中进行了一些改动和完善,

unit uHardWorkThread;

interface

uses
  Windows, Messages, Classes, SysUtils, SyncObjs;

const
  WM_QUIT_HARD_THREAD = WM_USER + 305;  //退出线程

type
  THardWorkThread = class(TThread)
  private
    FMsgHandle:THandle;                               //消息目的窗口句柄
    FErrorCount:Integer;                              //连续错误次数
    FIsWorking:boolean;                               //是否正在工作
    FIsSuspending:Boolean;                            //是否正在挂起
    FQuitEvent:TEvent;                                //退出线程事件
    FRunEvent:TEvent;                                 //运行事件,有信号表示运行
    FWorkCompletedEvent:TEvent;                       //工作完成事件, 有信号表示完成
    FPIsInterrupt:PBoolean;                           //中断
  protected

    function  WaitForWorkCompleted(const AWaitTime:Integer):Boolean;        //等待线程工作完成
    procedure SetupWorkCompleted(AWorkCompleted:Boolean);                   //设置线程工作状态
    procedure ImmediatelySuspend;                                           //立即挂起,一般继承子孙类内部用
    procedure Execute; override;
    procedure DoWorkProc(const APIsInterrupt:PBoolean); virtual; abstract;  //实际的工作过程(虚方法,子类必须实现)
  public
    constructor Create(AMsgHandle:THandle); virtual;                        //这个句柄注意,当消息目的窗体的Position变化时,窗体的Handle就变了(比如Dock窗体)
    destructor Destroy; override;

    procedure StartThread;                                                  //开始线程
    function  ExitThread(const AWaitTime:Integer):Boolean;                  //退出线程
    function  SuspendThread(const AWaitTime:Integer):Boolean;               //挂起线程
    procedure ResumeThread;                                                 //恢复线程
    property  MsgHandle:THandle read FMsgHandle write FMsgHandle;           //消息句柄
    property  ErrorCount:Integer read FErrorCount;
  end;

implementation

{ THardWorkThread }

constructor THardWorkThread.Create(AMsgHandle: THandle);
begin
  inherited Create(True);

  FMsgHandle:=AMsgHandle;

  FQuitEvent:=TEvent.Create;
  FRunEvent:=TEvent.Create;
  FRunEvent.ResetEvent;
  FWorkCompletedEvent:=TEvent.Create;
  FWorkCompletedEvent.SetEvent;
  New(FPIsInterrupt);
  FPIsInterrupt^:=False;

  FErrorCount:=0;
  FIsWorking:=False;
  FIsSuspending:=True;
  //FreeOnTerminate:=True;  //不要自动释放
end;

destructor THardWorkThread.Destroy;
begin
  Dispose(FPIsInterrupt);
  FWorkCompletedEvent.Free;
  FRunEvent.Free;
  FQuitEvent.Free;

  inherited;
end;

{
procedure THardWorkThread.DoWorkProc;
begin

end;
}
procedure THardWorkThread.Execute;
var
  Msg:TMsg;
begin
  while True do
  begin
    if PeekMessage(Msg,0,0,0,PM_REMOVE) then
    begin
      if Msg.message = WM_QUIT_HARD_THREAD then
      begin
        FQuitEvent.SetEvent;
        Break;
      end;
    end;

    if FPIsInterrupt^ then
    begin
      Continue;
    end;
    //等待运行
    FIsSuspending := True;
    FRunEvent.WaitFor(INFINITE);
    FIsSuspending := False;
    //退出时,如果线程挂起,则要恢复线程,然后退出
    if PeekMessage(Msg,0,0,0,PM_NOREMOVE) then
    begin
      if Msg.message = WM_QUIT_HARD_THREAD then
        Continue;
    end;

    if FPIsInterrupt^ then
    begin
      Continue;
    end;

    SetupWorkCompleted(False);          //开始工作
    try
      DoWorkProc(FPIsInterrupt);
    finally
      SetupWorkCompleted(True);        //完成工作
    end;

    Sleep(100);
  end;
end;

function THardWorkThread.ExitThread(const AWaitTime: Integer): Boolean;
begin
  Result:=True;
  FPIsInterrupt^:=True;
  PostThreadMessage(ThreadID,WM_QUIT_HARD_THREAD,0,0);
  if FIsSuspending then
    ResumeThread;
  //PostThreadMessage(ThreadID,WM_QUIT_HARD_THREAD,0,0);
  if FQuitEvent.WaitFor(AWaitTime) = wrTimeOut then
    Result:=False;
end;

procedure THardWorkThread.ImmediatelySuspend;
begin
  FRunEvent.ResetEvent;
  //FIsSuspending := True;
end;

procedure THardWorkThread.ResumeThread;
begin
  FRunEvent.SetEvent;
  //FIsSuspending := False;
end;

procedure THardWorkThread.SetupWorkCompleted(AWorkCompleted: Boolean);
begin
  FIsWorking:=not AWorkCompleted;
  if AWorkCompleted then
  begin
    FWorkCompletedEvent.SetEvent;
  end
  else
  begin
    FWorkCompletedEvent.ResetEvent;
  end;
end;

procedure THardWorkThread.StartThread;
begin
  Start;
end;

function THardWorkThread.SuspendThread(const AWaitTime: Integer): Boolean;
begin
  Result:=False;
  if FIsSuspending then
  begin
    Result:=True;
  end
  else
  begin
    if WaitForWorkCompleted(AWaitTime) then
    begin
      FRunEvent.ResetEvent;
      FIsSuspending:=True;
      Result:=True;
    end;
  end;
end;

function THardWorkThread.WaitForWorkCompleted(const AWaitTime: Integer): Boolean;
begin
  Result:=True;
  if FIsWorking then
    Result:=FWorkCompletedEvent.WaitFor(AWaitTime) = wrSignaled;
end;

end.


原文地址:https://www.cnblogs.com/jankerxp/p/7774030.html