• 关于线程的停止和挂起


    在用线程的时候经常要启动和挂起,原来d7的时候可以用resume和suspend(但是,建议不要用这2个方法,因为这2个方法在操作系统层面会造成死锁),现在版本的TThread里已经把这2个方法声明为deprecated(我用的是xe2,具体不知道从哪个版本起)。原来在D7的时候要挂起线程,也没用suspend,也是自己实现。

    参考置顶帖(现在好象没了,只有推荐了,见 http://bbs.csdn.net/topics/360046056 ),主要是参考它的退出线程方法,写了个"通用"线程。

    注:实际也不通用,我的情况是通用于主从方式的数据采集,某些系统资源,比如串口什么的,数据采集线程和主线程共用,也就是一般情况下,数据采集线程通过串口循环不断采集下位机的数据,当需要时,主线程可以挂起数据采集线程,让出资源(串口)供主线程用。

    数据采集线程中,资源(串口)占用时候时间有长有短,长的时候可能数秒,主线程发出挂起命令后,采集线程不一定马上结束工作,因而要判断采集线程是否真正完成了"工作",主线程是否可以用资源(串口)了,这里就有一个等待采集线程工作完成的问题。

    代码用起来虽然没发现有什么问题,不过感觉有点别扭,等待以后改进了


    unit unHardWorkThread;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.Classes, System.SysUtils, System.SyncObjs,
      unGeneral;
    
    const
      WM_QUIT_HARD_THREAD = WM_USER + 301;
      DELAY_TIME_MIN      = 10;
    
    type
      THardWorkThread = class(TThread)
      private
        FQuitEvent:TEvent;                              //退出线程
        FSuspendEvent:TEvent;                           //挂起线程事件,有信号表示正在工作,无信号表示已经挂起
        FWorkEvent:TEvent;                              //正在工作事件
        FPIsInterrupt:PBoolean;                         //中断
        FDelayTime:Word;                                //延迟
        FIsWorking:Boolean;                             //是否工作中
      protected
        SupervisorCtl:TObject;                          //管理者对象
        MsgHandle:THandle;                              //消息目的窗口句柄
    
        ErrorCount:Integer;                             //连续错误次数
    
        procedure Execute; override;
        procedure DoWorkProc(const APIsInterrupt:PBoolean); virtual; abstract;  //实际的工作过程(虚方法,子类必须实现)
      public
        constructor Create(ASupervisorCtl:TObject; AMsgHandle:THandle; ADelayTime:Word);
        destructor Destroy; override;
    
        function  ExitThread(const AWaitTime:Integer):Boolean;                  //退出线程
        function  SuspendThread(const AWaitTime:Integer):Boolean;               //挂起线程
        function  ResumeThread(const AWaitTime:Integer):Boolean;                //恢复线程
        function  WaitForWorkCompleted(const AWaitTime:Integer):Boolean;        //等待线程工作完成
    
      end;
    
    implementation
    
    { THardWorkThread }
    
    constructor THardWorkThread.Create(ASupervisorCtl: TObject; AMsgHandle: THandle; ADelayTime:Word);
    begin
      inherited Create(True);
    
      SupervisorCtl:=ASupervisorCtl;
      MsgHandle:=AMsgHandle;
    
      FQuitEvent:=TEvent.Create;
      FSuspendEvent:=TEvent.Create;
      FWorkEvent:=TEvent.Create;
      New(FPIsInterrupt);
      FPIsInterrupt^:=False;
    
      FIsWorking:=False;
      ErrorCount:=0;
      FDelayTime:=ADelayTime;
    
    end;
    
    destructor THardWorkThread.Destroy;
    begin
      Dispose(FPIsInterrupt);
      FWorkEvent.Free;
      FSuspendEvent.Free;
      FQuitEvent.Free;
    
      inherited;
    end;
    
    {
    procedure THardWorkThread.DoWorkProc;
    begin
    
    end;
    }
    procedure THardWorkThread.Execute;
    var
      Msg:TMsg;
    begin
      FreeOnTerminate:=True;
    
      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;
    
        FSuspendEvent.WaitFor(INFINITE);
    
        if FPIsInterrupt^ then
        begin
          Continue;
        end;
    
        FIsWorking:=True;
        FWorkEvent.ResetEvent;
        try
          DoWorkProc(FPIsInterrupt);
        finally
          FWorkEvent.SetEvent;
          FIsWorking:=False;
        end;
    
        if FDelayTime > DELAY_TIME_MIN then
        begin
          if DelayCanInterrupt(FDelayTime,FPIsInterrupt) then
            Continue;
        end;
      end;
    
    end;
    
    function THardWorkThread.ExitThread(const AWaitTime: Integer): Boolean;
    begin
      Result:=True;
      PostThreadMessage(ThreadID,WM_QUIT_HARD_THREAD,0,0);
      FPIsInterrupt^:=True;
      if FQuitEvent.WaitFor(AWaitTime) = wrTimeOut then
        Result:=False;
    end;
    
    function THardWorkThread.ResumeThread(const AWaitTime: Integer): Boolean;
    begin
      FSuspendEvent.SetEvent;
      Result:=True;
    end;
    
    function THardWorkThread.SuspendThread(const AWaitTime: Integer): Boolean;
    const
      Def_WaitTime = 10;
    begin
      Result:=False;
      if FSuspendEvent.WaitFor(Def_WaitTime) = wrSignaled then
      begin
        if WaitForWorkCompleted(AWaitTime) then
        begin
          FSuspendEvent.ResetEvent;
          Result:=True;
        end;
      end
      else
      begin
        FSuspendEvent.ResetEvent;
        Result:=True;
      end;
    end;
    
    function THardWorkThread.WaitForWorkCompleted(const AWaitTime: Integer): Boolean;
    begin
      if FIsWorking then
        Result:=FWorkEvent.WaitFor(AWaitTime) = wrSignaled
      else
        Result:=True;
    end;
    
    end.

    这里用了workevent,isworking,suspendevent,感觉有点乱,暂时还不清楚怎么简化。


  • 相关阅读:
    supervisor 3.0a81 安装失败
    nginx使用HttpImageFilterModule
    docky模式下背景不透明
    一堆DLL中找一个类
    Python中序列化处理之——marshal和cPickle篇
    Mercurial host fingerprint warning
    Python中时间的处理之——tzinfo篇
    ServiceStack.Redis的问题与修正
    Python中时间的处理之——datetime篇
    Rdesktop 1.6.0 and Windows Server 2008 SP2
  • 原文地址:https://www.cnblogs.com/jankerxp/p/7774038.html
Copyright © 2020-2023  润新知