该线程如何处理?(10分)

  • 主题发起人 主题发起人 云飘飘
  • 开始时间 开始时间

云飘飘

Unregistered / Unconfirmed
GUEST, unregistred user!
窗体上设置一按钮,每次单击则执行线程tmythread.execute中的代码,不需循环
按钮.onclick中tmythread.create(false);可总不能每次都创建它吧
如果是每次创建tmythread,那么tmythread.execute执行完后,在哪里terminate它比较合适呢
或者有更好的办法?
多谢!
 
可以放在create中,看这里楼主的代码 :
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2520822
 
可能是要每次都创建。。
 
线程的退出有两种:
1 自动退出,是指线程在完成其EXECUTE后直接返回,些时FREEONTERMINATE属性设为TRUE;线程对象会被自动删除,并释放对象所占用的资料。
2 受控退出,利用线程对象的terminate可以由进程或其它线程控制退出,设置terminate为TRUE就可以了。
 
那么在哪里判断excute执行完呢?
这样就可以terminate它了
多谢
 
我用的是自动退出,可总有异常
故而想改用受控退出,所以问怎么判断excute执行完?
 
最笨的方法,设一个布尔变量,执行完为TRUE;没执行完FALSE;当为TRUE里就退出。
 
这个方法我想到了 但挺笨的不是,
所以我采用了waitfor,
button.onclick中我这样写
mythread.create(false);
mythread.waitfor;
mythread.terminate;
各位看对不对呀
 
首先补充怡.梦兄说的那个。。他说的可能不是太清楚。。。(^_^等我发帖子时候他那又改清楚了)
1 自动退出。就是在Execute(线程体)执行完之前,将对象的FreeOnTerminate设为True
(实际上一般可以在开始线程之前就设,这样会自动清空资源)
2 受控退出,其实是这样的,本质上,就是设一个逻辑变量T,在线程循环体中这样:
While Tdo
begin
...
end;
这样,主线程想让子线程停止的时候设T:=false就可以了。。而怡.梦说的那个,是利用
线程的Terminate这个属性,作为控制运行 or 停止 的逻辑变量。。。
以前我做的那个文件分割的程序,因为需要能中途停止,所以就用了第2种方式,这样在
每复制完一个文件块,都有机会停止。。。
另外,线程excute执行结束,会激发线程对象的OnTerminate事件,定义这个过程
并且把过程名(指针)赋给OnTerminate就可以了。。注意定义的格式一定要象下面这样
比如: procedure Tform1.a(sender:TObject) ;
您说的异常。。。能不能说下,具体什么异常?
 
mythread.create(false);
mythread.waitfor;
mythread.terminate;
云飘飘兄,您方法是可以的,语法上没有错误。。但是有一个问题。。
waitfor方法会导致当前线程的阻塞,也就是停止运行,那么,可能同样有停止响应的可能。。
 
刘麻子说的对 确实是停止了响应,怎么办才好呢,急死了
请问刘麻子,你的文件复制程序怎么判断了复制完一个文件块了呢
这也正是我的问题,只要在判断出execute执行完后,terminate它就ok了
我用waitfor就是为此目的 不用waitfor,该怎么判断呢
 
异常是 canvasdo
es not allow drawing
 
我那个是用begin
Thread创建线程的。。线程体是这样的(也就是象上面说的第而种方法):
procedure fgfile;
//分割文件线程
var
M:integer;
//第几个块
flen:longword;//源文件长度
sub:string;
//M转化为串
begin
sfile:=Tfilestream.Create(form1.MaskEdit1.EditText,fmopenread);
flen:=sfile.Size;
//源文件长度
M:=0;
while(flen>=block)and(run) do
begin
if M<10 then
sub:='.00'+inttostr(M)
else
if M<100 then
sub:='.0'+inttostr(M)
else
if M<1000 then
sub:='.'+inttostr(M);
dfile:=TFileStream.Create(form1.MaskEdit2.EditText+sub,fmcreate);//新建
dfile.CopyFrom(sfile,block);
dfile.Free;
flen:=flen-block;
M:=M+1;
end;
if (run)and(flen<>0) then
begin
if M<10 then
sub:='.00'+inttostr(M)
else
if M<100 then
sub:='.0'+inttostr(M)
else
if M<1000 then
sub:='.'+inttostr(M);
dfile:=TFileStream.Create(form1.MaskEdit2.EditText+sub,fmcreate);//新建
dfile.CopyFrom(sfile,flen);
dfile.Free;
M:=m+1;
end;
if run=false then
begin
for M:=M-1do
wnto 0do
begin
if M<10 then
sub:='.00'+inttostr(M)
else
if M<100 then
sub:='.0'+inttostr(M)
else
if M<1000 then
sub:='.'+inttostr(M);
if FileExists(form1.MaskEdit2.EditText+sub) then
deletefile(form1.MaskEdit2.EditText+sub);
end;
end;
sfile.free;
//保存文件
end;
这样创建: myth:=begin
Thread(nil,0,@fgfile,nil,0,ThID);

myth:Thandle;
//线程句柄
ThID:DWORD;
//线程ID
 
其实 第二种方法也可以自动 清除。。。只是可以受控制的停止。。。。 还有:
另外,线程excute执行结束,会激发线程对象的OnTerminate事件,定义这个过程
并且把过程名(指针)赋给OnTerminate就可以了。。注意定义的格式一定要象下面这样
比如: procedure Tform1.a(sender:TObject) ;
另外,怎么用begin
Thread创建线程线程?
要定义一个函数或过程,格式随意,比如 :
procedure pro;
begin
。。。。。
end;

function begin
Thread(
Security Attributes:Pointer;
//指向一个结构的指针,可设为 nil
StackSize:Integer;
//指定线程将被分配的堆栈,0表示用默认值
ThreadFunc:TThreadFunc;
//这个就是前面定义的函数,作为线程体,形式:@函数名
Parameter:Pointer;
//这个是为了传递参数给ThreadFunc的指针
CreationFlags:Integer;
//创建线程之后是否立即执行。0表是立即执行,4表示挂起
VarTHreadID:Integer //这个参数要用变量,用来接收创建的线程的识别号
):integer;
//返回值是线程的句柄,如果是0表示没有创建成功
所以我们就可以 myth:=begin
Thread(nil,0,@pro,nil,0,ThID);

这样建立的线程应该是自动删除的。。。
另外,你定义的线程是否能贴出来看看?
 
是否在线程中用了showmessage.... 你单步执行,看看错在哪里。。。
 
assignfile(f,tstring);
rewrite(f);
writeln(f,'开始时间:'+DateTimeToStr(now));
writeln(f,'SDE源数据库'+trim(form1.MServer.Text)+'——〉'
+'SDE目标数据库'+trim(form1.EServer.Text));
closefile(f);
assignfile(f,tstring);
append(f);
writeln(f,'数据转移方式:用户自定义');
writeln(f,'操作: 选定SDE源数据库内容列表中的若干个图层,将其导入SDE目标数据库');
if form1.Slist.SelCount=0 then
begin
showmessage('请先在源数据库中选择要传送的图层!');
exit;
end;

transfering:=true;

scount:=form1.Slist.SelCount;
for i:=0 to form1.Slist.Items.Count-1do
begin
if form1.Slist.Selected then
writeln(f,form1.Slist.items);
end;
writeln(f,'操作结果:');
for i:=0 to form1.Slist.Items.Count-1do
begin
if form1.Slist.Selected then
begin
name:=form1.Slist.Items;
j:=0;
while j<form1.Mlist.Items.countdo
begin
if form1.Mlist.Items[j]=name then
break;
inc(j);
end;
if j=form1.Mlist.Items.Count then
begin
form1.statusbar1.SimpleText:='SDE目标数据库中缺少'+name+'图层!'+'请先用ArcInfo新建所缺文件!';
writeln(f,'SDE目标数据库中缺少'+name+'图层!');
messagedlg('SDE目标数据库中缺少'+name+'图层!',mtwarning,[Mbok],0);
continue;
end;
if form1.modify(name)=false then
begin
form1.statusbar1.SimpleText:='目标数据库中图层'+name+'改建有误!';
writeln(f,'目标数据库中图层'+name+'改建有误!');
messagedlg('目标数据库中图层'+name+'改建有误!',mtwarning,[mbok],0);
continue;//modify用于改建图层,保持文件结构,清空内容
end;
try
form1.statusbar1.Simpletext:='正在传送图层'+name+'的数据,请等待……';
Slyr.GeoDataSet:=IMOGeoDataset(Ssdecon.FindGeoDataset(Name));
SRecSet:=Slyr.Records;
lyr.GeoDataset:=IMOGeoDataset(SDECon.FindGeoDataset(name));
RecSet:=lyr.Records;
tcount:=SRecSet.TableDesc.FieldCount;
SRecSet.MoveFirst;
while not SRecSet.eofdo
begin
RecSet.AddNew;
RecSet.Fields.Item('shape').Value:=SRecSet.Fields.Item('shape').Value;
for k:=0 to tcount-1do
begin
str:=SRecSet.TableDesc.FieldName[k];
RecSet.fields.Item(str).Value:=SRecSet.Fields.Item(str).Value;
end;
RecSet.Update;
RecSet.StopEditing;
SRecSet.MoveNext;
end;
form1.Slist.Selected:=false;
dec(scount);
form1.statusbar1.Simpletext:=name+'传送成功,目标数据库中的改建为空的'+name+'已经恢复!';
writeln(f,name+'传送成功!');
except
form1.statusbar1.Simpletext:=name+'传送失败,目标数据库中的改建为空的'+name+'没能恢复!';
writeln(f,name+'传送失败!');
messagedlg('数据传送失败!',mtwarning,[mbok],0);
continue;
end;
end;
if scount=0 then
break;
end;
writeln(f,'完成时间:'+DateTimeToStr(now));
closefile(f);
messagedlg('数据传送完毕! 请查看日志文件,以获取详细操作结。',mtinformation,[mbok],0);
[red] transfering:=false;[/red]
如果自动删除的话,总是出现异常,不知是何原因,绿色箭头指向transfering:=false;一行,异常为EInvalidoperation:canvasdo
es not allow drawing!
 
用了messagedlg ,这有什么关系吗?
可把messagedlg一句去掉反而没有异常了
不知道这是什么原因阿
可是线程不是自动删除时怎么没出现过这种异常呢?
 
可能就是messagedlg的原因,一般在线程中不要访问界面,似乎会导致死缩。。。
我以前在线程中用showmessage也是类似的情况...
 
线程里分两种情况,另外一我没写出来
两种情况下都有一样的messagedlg
一种情况下就没问题,另外一种情况下就总有问题 费解!
若不用showmessage 和messagedlg
那怎么在线程结束时,弹出对话框呢,请多指教 thanks a lot!
 
下午和你说....有办法的....放心! ^_^
你先去掉messagedlg看看错误是否还在?
 
后退
顶部