多线程操作问题:
如:
var
MainFrm: TMainFrm;
th : THComm2PDA;//线程对象
...
procedure TMainFrm.btSendClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
th:= THComm2PDA.Create(False);
end;
procedure TMainFrm.btGetClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
th:= THComm2PDA.Create(False);
end;
procedure TMainFrm.btStopClick(Sender: TObject);//最郁闷在这儿了
begin
if th<>nil then th.Terminate;
end;
调试的时候发现创建线程后,每次点击‘btStop’时,th总是为线程对象,难道th.Terminate没有终止线程???
或者要如何才能确保我在2次创建线程时必须终止第一次创建的线程??
没有办法了,该程序用于连接串口,而串口设备为半双工(晕),设备要么处于发送状态,要么处于接收状态,通过线程的Create参数确定设备处于何种状态,如果2次线程创建时上一次线程没有终止,肯定会出错,线程中有串口打开操作等
如:
var
MainFrm: TMainFrm;
th : THComm2PDA;//线程对象
...
procedure TMainFrm.btSendClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
th:= THComm2PDA.Create(False);
end;
procedure TMainFrm.btGetClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
th:= THComm2PDA.Create(False);
end;
procedure TMainFrm.btStopClick(Sender: TObject);//最郁闷在这儿了
begin
if th<>nil then th.Terminate;
end;
调试的时候发现创建线程后,每次点击‘btStop’时,th总是为线程对象,难道th.Terminate没有终止线程???
或者要如何才能确保我在2次创建线程时必须终止第一次创建的线程??
没有办法了,该程序用于连接串口,而串口设备为半双工(晕),设备要么处于发送状态,要么处于接收状态,通过线程的Create参数确定设备处于何种状态,如果2次线程创建时上一次线程没有终止,肯定会出错,线程中有串口打开操作等
解决方案 »
- import type library中有个控件被移除怎么恢复?
- 如何用tchart控件实现多轴显示
- 数据库用access,如何取局域网中另一台机器的时间?
- 求教:查看电脑上程序自启动问题及查看进程相关问题
- 谁知道如何获得当前声音的电平值(振幅)?
- 在一个我自己编写的控件中使用了字符串资源文件和一个*.dfm文件,在发布的时候一定也要发布该资源文件和dfm文件吗?
- 救急:如何用DELPHI复制引导扇区
- 如何在DELPHI中实现能播放多种文件格式的多媒体程序(如超级解霸2001XP)
- 用TQUERY访问ACCESS数据库时!难道一定要用数据源吗,不可以直接访问所在目录吗?
- 一个报表的困惑
- 我们知道windowfrompoint可以用来获得当前鼠标指向的控件的句柄,那么我如何……
- memo控件能修改行距吗?
procedure TForm1.Button1Click(Sender: TObject);
begin
try
if form2=nil then
form2:=TForm2.Create(application);
form2.ShowModal;
finally
form2.Free;
end;
end;
MainFrm: TMainFrm;
th : THComm2PDA;//线程对象
...
procedure TMainFrm.btSendClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
th:= THComm2PDA.Create(False);
th.OnTerminate := thTerminate; // 新增
end;
procedure TMainFrm.btGetClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
th:= THComm2PDA.Create(False);
th.OnTerminate := thTerminate; // 新增
end;
procedure TMainFrm.btStopClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
end;procedure TMainFrm.thTerminate(Sender: TObject); // 新增
begin //
th := nil; //
end; //
但仅仅这样做还不够,如上所说,th.Terminate 等同于 th.Terminated := True;
因此 th.Terminate 不能造成线程 th 的终止,“和平”的终止线程的方法应该是:线程自己退出 Execute() 函数,该线程即告终止。
所以要在 THComm2PDA.Execute() 中不时地检测一下自己的 Terminated 属性,如果为 True,就退出函数。
不分场合,不分地点,不分时间 大家宣传一下:
一组数据,日本对中国的依赖程度现排最前,特别是对中国市场的依赖,
如果中国人1个月不买日货,日本将有数千家企业面临破产。
如果中国人6个月不买日货,日本将有一半人失业。
如果中国人1年不买日货,日本经济结构彻底瓦解,日本还能这样嚣张吗!
你如果是中国人,不用你上战场当炮灰,
你要做的事很简单,就是不买日货。
抵制日货网络签名处:http://www.dzrhlm.com/book/
抵制日货网络签名处:http://www.dzrhlm.com/book/
抵制日货网络签名处:http://www.dzrhlm.com/book/
抵制日货网络签名处:http://www.dzrhlm.com/book/
抵制日货网络签名处:http://www.dzrhlm.com/book/
抵制日货网络签名处:http://www.dzrhlm.com/book/
抵制日货网络签名处:http://www.dzrhlm.com/book/
抵制日货网络签名处:http://www.dzrhlm.com/book/
if th<>nil then
begin
th.Terminate;
FreeAndNil(th);
end;
在线程的excute函数中已经检测了Terminated属性了,如果这个属性为true时,excute将会马上结束,问题就在这儿了,结束后线程依然不为nil,
除了 FreeAndNil(th);还有别的办法吗?
只能这样吗?
th.Terminate;
FreeAndNil(th);
感谢各位,还有点不明白,直接调用FreeAndNil会不会导致我的线程不会正常结束?如果不是正常结束,还是会有问题的,我在线程中打开了串口。
你说的办法确实能保证全局线程对象退出后变成nil,可是程序并不能这么写,原因如下
var
MainFrm: TMainFrm;
th : THComm2PDA;//线程对象
...
procedure TMainFrm.btSendClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
th:= THComm2PDA.Create(False);
th.OnTerminate := thTerminate; // 新增
to DDGG(叮叮当当):问题在这!!
当运行th.Terminate后,又马上创建了th对象,这时候并不能保证我在创建th之前th为nil!
在th中需要初始化串口和半双工串口设备,如果上一个th没有结束,初始化肯定会出问题,th中有sleep函数,通过循环检测Terminated属性实现串口的持续数据接收,如果不用线程的话,这个问题可以解决,但是不用线程的结果是主程序将陷入死循环,且桌面停止响应(这个就不用多解释了)
在线程的excute函数中检测了Terminated属性,线程是可以正常结束的。
end;
procedure TMainFrm.btGetClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
th:= THComm2PDA.Create(False);
th.OnTerminate := thTerminate; // 新增
end;
procedure TMainFrm.btStopClick(Sender: TObject);
begin
if th<>nil then th.Terminate;
end;procedure TMainFrm.thTerminate(Sender: TObject); // 新增
begin //
th := nil; //
end;
感谢参与,有再次看到的,欢迎讨论……
明天结贴
procedure TMainFrm.btSendClick(Sender: TObject);
if th<>nil then th.Terminate; th.WaitFor; //增加的代码,等待线程结束
FreeAndNil(th); //如果th.FreeOnTerminate则用th=nil th:= THComm2PDA.Create(False);
th.OnTerminate := thTerminate; 2.procedure TMainFrm.thTerminate(Sender: TObject);
begin
th := nil; if ... then begin //不一定要创建新的线程,加上适当判断
th:= THComm2PDA.Create(False);
th.OnTerminate := thTerminate;
end
end; 第一种情况适于线程可以很快结束的情况(<0.5秒),否则会有UI延迟.另外,中止线程还有一种方法:
对于依赖某种句柄的线程,可以直接在线程外关闭这个句柄,线程自然直接结束,快速有效.另外,任何时候,在线程的Execute中都要有适当的try...except.