我的程序中有两个串口控件,分别控制两个机械设备完成相应的工作。我的一个任务,需要两个设备来组合完成。我现在要连续完成n个相同的任务,这样我就想到了使用线程,这样可以充分利用两个设备同时做自己要做的事。我的一个任务的过程是这样的:
1、设备A动作;
2、设备B动作;
3、设备A动作;
当然,我的一个动作中肯定需要com发送几个命令。我的线程中的Execute是这样写的(因为用到窗体中的com控件,所以使用了synchronize):
procedure TAutoThread.Execute;
begin
  //执行完毕自动释放
  FreeOnTerminate := True; 
  //使用设备A
  Synchronize(DoCtrlIn);
  //等待
  Sleep(nDelay * 1000);
  //使用设备B
  Synchronize(AnalysisBmp);
  //使用设备A   
  Synchronize(DoCtrlOut);
end;由于一个动作是几个命令的组合,我为了防止线程1的一个设备的一组动作还没完成的时候被另一个线程控制同一个设备的命令插入进去,我在DoCtrlIn这些函数中使用了临界区,其中一个函数如下:
procedure TAutoThread.DoCtrlOut();            //排
begin    
  EnterCriticalSection(csCtrl);  //发送转盘命令             
  frmJingjian.CtrlTurnTable(FTurntableIndex);
  //排液           
  frmJingjian.New_CtrlSelectChannel_Clear(FChannelIndex);
  //清洗
  frmJingjian.New_CtrlClearWall(False);
  //抬针               
  frmJingjian.New_CtrlUp_All();
  
  LeaveCriticalSection(csCtrl);
end;csCtrl是设备A的临界区,csMic是设备B的临界区。另两个函数类似。现在还是出现了当前线程一个函数还没执行完的时候,另一个线程的同一个函数的命令插入进去了的情况。请问这是什么原因?实在想不明白是怎么回事……在线等待,请高手们关注一下……

解决方案 »

  1.   

    FreeOnTerminate := True;不能写在Execute方法里.写在Create里面.
      

  2.   

    既然所有方法都是Synchronize的 就是说实际上所有操作都已经在主线程里完成了
    那么你的情况就没有必要使用多线程   
    一个任务过程可以写成这样
      DoCtrlIn;
      开始一个定时器并设置周期nDelay * 1000 事件为TimerHandler
    procedure TimerHandler;
    begin
      AnalysisBmp;
      DoCtrlOut;
    end;
    这种写法与你使用多线程的效果是相同的尝试把多线程的代码移除 然后检查问题是不是出在程序本身的逻辑里
      

  3.   

    我也想到了这个问题,所有工作都是在主线程中进行的。为什么要使用多线程,主要考虑在单一的任务中,设备A工作的时候,设备B是不工作的。因为我现在要同时进行几个相同的任务,如果可以让第一个任务中的设备B工作的时候,第二个任务中的设备A同时也工作,不是可以节省时间嘛。FreeOnTerminate := True;不能写在Execute方法里.写在Create里面????
    怎么不可以呢?搞不明白,我都用了几年了!!!
      

  4.   

    个人认为临界区应该使用得没什么问题。  //使用设备A
      Synchronize(DoCtrlIn);
      //等待
      Sleep(nDelay * 1000);
      //使用设备B
      Synchronize(AnalysisBmp);这里面的等待觉得有些问题。这个等待的功能估计是为了使设备A完成某个动作,然后开始使用设备B。由于这个等待不在临界区内使用,所以在等待的时候,其他线程就有机会执行Synchronize(DoCtrlIn);了。
      

  5.   

    采用前述利用定时器等待的方法 同样可以在Delay这段时间里开始做另一个任务,而这个其实就是你用线程所达到的目的
      

  6.   

    你的代码里不论是操作设备A 和设备B的过程都是在Synchronize里的 所以它们不可能同时进行——总是在主线程里被顺序执行
    所以实际上你代码里的临界区 是多余的
      

  7.   

    出差了1个星期,没有看大家的问题,请多多包含!!!1、用Sleep(nDelay * 1000)来等待,是一个任务中处理的需要,在等待之前,我能够保证设备A的动作已经完成。我的初衷就是考虑用这个等待的时间可以开始第二个任务,因为这个时候第一个任务已经不使用设备A了。
    2、定时器的方法,有些不明白。还请教当要处理多个相同的任务,定时器怎么处理逻辑关系?因为第一个任务结束后,第二个任务基本上还有可能没有完成,这是肯定要开始执行第三个任务。或者还有可能第二个任务比第一个先完成。
      

  8.   

    DoCtrlIn;
    with TTimer.Create(Self) do
    begin
      Interval=nDelay * 1000;
      //Tag = ...
      OnTimer=TimerHandler;
      Enabled = True;
    end;procedure TimerHandler(Sender);
    begin
      TTimer(Sender).Enabled = False;
      //xxx = TTimer(Sender).Tag
      AnalysisBmp;
      DoCtrlOut;
      TTimer(Sender).Free;
    end;