zoukankan      html  css  js  c++  java
  • 关于线程的停止、挂起、退出(修改)

    原来的实现: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.


  • 相关阅读:
    kmp 算法
    jdk 和 cglib 的动态代理
    RestTemplate工具类
    bat脚本切换多个工程的分支
    字符串的左旋转
    输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5、4~6和7~8。
    枚举类型在JPA中的使用
    拾遗
    YAML DEMO
    kiali 1.26 anonymous策略修改为token
  • 原文地址:https://www.cnblogs.com/jankerxp/p/7774030.html
Copyright © 2011-2022 走看看