我的程序中有两个串口控件,分别控制两个机械设备完成相应的工作。我的一个任务,需要两个设备来组合完成。我现在要连续完成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、设备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的临界区。另两个函数类似。现在还是出现了当前线程一个函数还没执行完的时候,另一个线程的同一个函数的命令插入进去了的情况。请问这是什么原因?实在想不明白是怎么回事……在线等待,请高手们关注一下……
解决方案 »
- 都有哪些比较好的第三方UI控件阿
- 我在使用WSARecv的时候一直遇到WSAEFAULT错误
- try... except在运行期间无法捕获异常(不显示错误信息)
- Delphi版的朋友辛苦了,新年好!顺便请教一个True DBGrid的问题!
- if嵌套问题,简单!
- 编译时报错如下,是什么原因,应该怎么解决呢??
- 请问各位高手:如何得到PageControl的页面数量总数?谢谢,另外,我怎么结不了帐?
- 请问如何是程序带参数执行
- 我在一个dll中调用了ADO,在delphi中调用没有问题,为什么在pb中一调用就说什么某个地址不能为只读?
- 菜鸟问题,变量前加一个@表示什么?比如@MyCount
- 很急!!!小女求大家了!!!!!!!在线等!!!!
- 怎样让程序重起
那么你的情况就没有必要使用多线程
一个任务过程可以写成这样
DoCtrlIn;
开始一个定时器并设置周期nDelay * 1000 事件为TimerHandler
procedure TimerHandler;
begin
AnalysisBmp;
DoCtrlOut;
end;
这种写法与你使用多线程的效果是相同的尝试把多线程的代码移除 然后检查问题是不是出在程序本身的逻辑里
怎么不可以呢?搞不明白,我都用了几年了!!!
Synchronize(DoCtrlIn);
//等待
Sleep(nDelay * 1000);
//使用设备B
Synchronize(AnalysisBmp);这里面的等待觉得有些问题。这个等待的功能估计是为了使设备A完成某个动作,然后开始使用设备B。由于这个等待不在临界区内使用,所以在等待的时候,其他线程就有机会执行Synchronize(DoCtrlIn);了。
所以实际上你代码里的临界区 是多余的
2、定时器的方法,有些不明白。还请教当要处理多个相同的任务,定时器怎么处理逻辑关系?因为第一个任务结束后,第二个任务基本上还有可能没有完成,这是肯定要开始执行第三个任务。或者还有可能第二个任务比第一个先完成。
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;