关于线程的停止和挂起

来源:互联网 发布:淘宝买家怎么改价格 编辑:程序博客网 时间:2024/05/21 10:41

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

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

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

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

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


unit unHardWorkThread;interfaceuses  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;beginend;}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,感觉有点乱,暂时还不清楚怎么简化。


原创粉丝点击