最近遇到一个非常棘手的问题,复现频率及其的低.
形同运行环境描述:
只在客户端复现过(客户端XP或者2003),我本地是win7问题描述:
在程序的主界面放了一个定时器控件,定时器Timer事件的逻辑如下,
tmrWork.Enabled := False;
tmrWork.Interval := 30 * 1000;  //不在运行时间,半分钟检测一次 
TSecThread.Create(StrList);TSecThread类如下
TSecThread = class(TThread)
  private
    strList:TStrings;
    ConText : TConText;
  public
    procedure Execute; override;
    procedure SetstrList(var strL:TStrings);
    constructor Create(var strL:TStrings);
  end;
constructor TSecThread.Create(var strL: TStrings);
begin
  SetstrList(strL);
  StataCon := TConText.Create(strList) ;
  FreeOnTerminate := True;
  inherited Create(False);
end;在线程TSecThread.Execute中处理逻辑如下,try finally部分做了业务处理,然后在finally end部分做了定时器的处理
  inherited;
  try
    ConText.NowState.SetNextState(); 
    Sleep(100);
    ConText.NowState.SetNextState(); 
    Sleep(100);
    ConText.NowState.SetNextState(); 
  finally
    if Assigned(ConText) then
      freeandnil(ConText);
    FmMain.tmrWork.Enabled := True;
  end;问题出现了,安装上面的逻辑,只能有一个TSecThread线程在执行,可是有的时候会出现两个TSecThread在执行,请问有人出现过这样的问题没有?怎么解决?

解决方案 »

  1.   


    procedure TSecThread.Execute;  
    var
      MsgRec: TMsg;
    begin
      inherited; 
      FCheckTimer := TTimer.Create(nil);
      FCheckTimer.Interval := 30*1000;
      FCheckTimer.OnTimer := procTimer;
      FCheckTimer.Enabled := true;  while GetMessage(MsgRec, 0, 0, 0) do
      begin
        TranslateMessage(MsgRec);
        DispatchMessage(MsgRec);
      end;        
      FCheckTimer.Enabled := False;
      FCheckTimer.free;
    end;procedure TSecThread.procTimer(Sender: TObject);
    begin
      FCheckTimer.Enabled := False;
      try
        //do something
      finally
        FCheckTimer.Enabled := true;
      end;
    end;
      

  2.   

    定时器不会很精确,你比如在TSecThread.Create(StrList);先做判断,
    定时器是主线程运行。
      

  3.   

    To:andrew57 
    没明白是什么意思.
      

  4.   

    没必要用定时器,也没必要反复创建和释放线程,直接在 Execute 中写一个循环:repeat
      // 这里是你的状态逻辑语句
      Sleep(30000);  // 等待半分钟重新开始
    until Terminated;这样就能不断循环处理,直到你把 Terminated 设成 True。为了能在终止时尽快反应,可以把 Sleep 缩短,用循环凑成半分钟,中间不断检测 Terminated 条件。
      

  5.   

    To:sz_haitao
    就是timerTo: jinghai1776
    这个办法比较好,不过看看还有其他的办法没有,改动有些大,这个是最后的选择了。
      

  6.   

    定时器事件怎么写的?
    定时器事件的代码没贴,不知道里面怎么写,有没有先停止自己再启动线程?如果的确是每次执行完停止30秒再重新执行,的确可以在线程里sleep
      

  7.   

    楼主不妨仔细思考下:你在线程里启动主线程定时器,又在定时器事件创建新线程,这就很可能两个线程同时存在,因为老线程释放需要一定时间。而且这种现象是随机的,因为这取决于操作系统如何分配 CPU 时间片。这种方案连想都不要想。
      

  8.   

    在timer中用 WaitForSingleObject(handle, 0);试试看
      

  9.   

    不建议反复创建线程,如果TSecThread.create肯定是在你timer事件之外你还有执行过,我觉得TSecThread有两个的原因不在timer,而是在timer之外TSecThread.create被执行过两次。
      

  10.   

    试着将恢复定时器的代码放到Thread的OnTerminate事件中
      

  11.   

     inherited;
      try
        ConText.NowState.SetNextState(); 
        Sleep(100);
        ConText.NowState.SetNextState(); 
        Sleep(100);
        ConText.NowState.SetNextState(); 
      finally
        if Assigned(ConText) then
          freeandnil(ConText);
        FmMain.tmrWork.Enabled := True;
      end;---------------------------------------------------------FmMain.tmrWork.Enabled := True;
    这句有问题。TTimer是独立于线程的对象。你这句应该用Synchronous执行。