多线程数组的问题. 如何判断状态???(100分)

  • 主题发起人 chenzhou
  • 开始时间
C

chenzhou

Unregistered / Unconfirmed
GUEST, unregistred user!
main.pas(主程序)
var aa:array of scanftp;
i:integer;

index:integer;
当前完成的线程数
index:=0;
//初始化
button1click() //新建线程
begin
setlength(aa,100)
for i:=0 to 9do
//线程数为10
begin
aa=scanftp.create(false);
//线程创建后自动执行
aa.FreeOnTerminate:=true;
//线程终止后自动释放内存
aa.OnTerminate:=OnThreadend;
index:=index+1;
end
end;

main.onthreadend() //线程完成后递归下一个线程
begin
if index>100 then
exit;
aa[index]=scanftp.create(false);
aa[index].FreeOnTerminate:=true;
//线程终止后自动释放内存
aa[index].OnTerminate:=OnThreadend;
index:=index+1;
end
button2click() //如何判断数组的状态 目的是想停止所有的线程
i:integer;
begin
for i:=0 to 99do

if ?????? then
//**********这个判断怎么写 判断这个线程是否新建、运行中、停止了//
begin
aa.terminate;
end;
end

scanftp.pas(线程)
scanftp.execute
begin
if terminated then
exit;
....
end;

问题原因是有的线程如第99个还没Create;有的线程如第1个已经运行完毕FREE了;有的在运行中如第10个;怎么判断这样的数组??
 
初始化 aa 为nil ,如果相应的线程终止,将 aa 设为 nil
这样就可以用 aa 来判断了。
如果为 nil 则没有对应的线程。
如果不为nil, 可根据 aa 的 suspended 和 terminated 属性来判断线程状态。
 
好象suspended 和 terminated 只能在scanftp.pas 就是线程的execute过程内才能用啊
 
试了一下还有个问题,如果aa初始化为nil,
则在aa:=scanftp.create(...)中会出现错误
线程无法新建了
 
给线程类中添加标志,表示该线程是否停止(如bool isTerminated),且在创建线程时设置参数为手工释放,
即FreeOnTerminate := true;,线程创建时isTerminated := false;退出前设置isTerminated := true;
这样你的循环判断就可以如下了:
for i:=0 to 99do

if aa.isTerminated then

begin
aa.terminate;
aa.Free;
//手工释放
end;

 
sorry ,代码写得有问题,更改如下:
for i:=0 to 99do
begin

if (not aa.isTerminated) then

begin
aa.terminate;
//未停止的线程强行中止
end;
aa.Free;
//手工释放所有线程资源
end;

 
Terminated 会触发 Onthreadend 事件
这个线程是停止的,但下个线程被递归调用又开始了,还在动怎么办
 
我有一个方案了
main.pas(主程序)
var aa:array of scanftp;
i:integer;

index:integer;
// 当前完成的线程数
exitscan:boolean;
// 全局控制是否被停止了
index:=0;
//初始化
exitscan:=false
button1click() //新建线程
begin
setlength(aa,100)
exitscan:=false;
~~~~~开始
for i:=0 to 9do
//线程数为10
begin
aa=scanftp.create(false);
//线程创建后自动执行
aa.FreeOnTerminate:=true;
//线程终止后自动释放内存
aa.OnTerminate:=OnThreadend;
index:=index+1;
end
end;

main.onthreadend() //线程完成后递归下一个线程
begin
if (index>100) or (exitscan) then
exit;
//不再新建线程
aa[index]=scanftp.create(false);
aa[index].FreeOnTerminate:=true;
//线程终止后自动释放内存
aa[index].OnTerminate:=OnThreadend;
index:=index+1;
end
button2click() //如何判断数组的状态 目的是想停止所有的线程
begin
{ for i:=0 to 99do

if ?????? then
//**********这个判断怎么写 判断这个线程是否新建、运行中、停止了//
begin
aa.terminate;}
//不用判断了 直接用全局变量来控制 不再建新线程
exitscan:=true;
button2.enabled:=false;
sleep(10000);
//不做任何事 只等旧线程完毕
button2.enabled:=true;
end;
}
end
scanftp.pas(线程)
scanftp.execute
begin
if terminated then
exit;
....
end;

To huntor:
aa.isTerminated ~~~ 我用的DELPHI6 这句话在main.pas(主程序)中 没有这个属性 所以还不是行
 
button2click() //如何判断数组的状态 目的是想停止所有的线程
Number, i:integer;
ExitCode: Cardinal;
begin
//可能要同步
Number := Index;
Index := 101;
//同步结束
for i:=0 to Number - 1do
try
if GetExitCodeThread(aa.Handle, ExitCode) and (ExitCode = STILL_ACTIVE) then
begin
aa.Terminate;
aa.WaitFor;
end;
except
end;
SetLength(aa, 0);
end
 
To wolaixue 在试
还有一个问题,如果线程开得太多,比如10000个,开始就错误怎么办.
说内存分配资源不足怎么办,会弹出很多窗口。
 
同时运行的线程总数应该控制。
可以在线程运行结束后再开。
 
怕是高档的服务器也经不起这样的折腾吧?
线程虽好,但不要滥用啊!
 
有道理啊,不能滥用。
我问题也解决了,用两个全局变量。scanlist:tlist exitscan:boolean;
来绑定多线程 找sleep 改成scanlist中判定有在进行线程,然后terminate;
 
多人接受答案了。
 
虽然结贴了,我还想把我的想法说清楚:
//aa.isTerminated ~~~ 我用的DELPHI6 这句话在main.pas(主程序)中 没有这个属性 所以还不是行
isTerminated这个属性要自己在线程类里添加(我偷懒,设置为公共变量),初始的时候赋值FALSE,停止的时候赋值TRUE
 
现在知道了. :)
不过这个isterminated 让我一直以为会不会是我的DELPHI6是盗版的。
感觉多线程还需要两个附加的变量来看状态,一个是isterminated看是不是被停止了.
一个是tlist绑定当前的运行中的线程。
 

Similar threads

C
回复
3
查看
302
coolingxyz
C
Q
回复
4
查看
297
穿越沦陷的爱
穿
W
回复
2
查看
222
lp414
L
顶部