CnPack Forum


 
Subject: 请教一个多线程退出的问题.
sunnyfairy
新警察
Rank: 1



UID 57476
Digest Posts 0
Credits 34
Posts 12
点点分 34
Reading Access 10
Registered 2011-1-3
Status Offline
Post at 2011-1-3 12:02  Profile | Blog | P.M. 
请教一个多线程退出的问题.

看了很多相关的书,在网上没有找到合适的答案, 这个论坛也没有合适的版块问题这类问题,只有发这里了.
这里的版主都是我葱白的偶像.望解答.

关于多线程终止的问题.

在多线程Execute中,一般我这样写:


while not Terninated do
begin
   //其它处理
  WaitForSingleObject(Handle, 1); //或Sleep(1);效果一样.
end;

这个线程从程序初始化完成之后一直运行着,直到程序退出时终止.

如果我
1. 在Create中已经FreeOnTerminated := True;此时线程终止时应该自动释放内存空间.

我在该单元的Finalization中有如下代码:
  if Thread.Suspended then   
    Thread.Resume;
  Thread.Terminate;

这样的结果是内存泄漏.

2.在Create时,FreeOnterminated := False; 此时我再定义一个单元内的变量GFinished: Boolean;用以标识线程是否结束.\
  在线程的OnTernimate方法中改写该变量 为True;
我在该单元的Finalization中有如下代码:
  if Thread.Suspended then   
    Thread.Resume;
  Thread.Terminate;
  while not GFinished do Application.ProcessMessages;
....
线程结束时会存在问题.特别是当线程间隔比较大时,比如Sleep(5分钟);导致程序一直等待.

就最常规的退出方法是什么?谢谢.

可能我的方法都不正确.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
第二个问题:
while not Terninated do
begin
   //其它处理
  WaitForSingleObject(Handle, 5分钟); //或Sleep(5分钟);
end;
主程序退出时,这个线程会被通知结束吗?也就是Terniamted会被自动置为True吗?如果不能,那怎么办,要用Event通知吗?

[ 本帖最后由 sunnyfairy 于 2011-1-3 12:06 编辑 ]
Top
Passion (LiuXiao)
管理员
Rank: 9Rank: 9Rank: 9


UID 359
Digest Posts 19
Credits 6766
Posts 3559
点点分 6766
Reading Access 102
Registered 2004-3-28
Status Offline
Post at 2011-1-3 19:25  Profile | Blog | P.M. 
Thread.Terminate;仅仅只会把线程内部的Termiated标志设置成True,线程的真正退出需要线程中检测到了Terminated变量为True后从Execute过程中退出。如果楼主的线程正在WaitforSingleObject或Sleep等待,就不能及时得到这个判断了。需要Thread.Waitfor后才能等待退出,其结果是退出延时很长。

一个最简单的改造办法是多次等待,同时减少等待时间,等待时同时判断Terminated
Sleep(5分钟);
改成
for i := 1 to 5*60 do
  if not Termiated then
    Sleep(1000);
  else
    Exit;
Top
sunnyfairy
新警察
Rank: 1



UID 57476
Digest Posts 0
Credits 34
Posts 12
点点分 34
Reading Access 10
Registered 2011-1-3
Status Offline
Post at 2011-1-5 13:22  Profile | Blog | P.M. 
多次等待是个好方法.
不过我的第1个问题里面为什么那样写的话,内存工具会报内存泄漏?

内存泄漏并不是自己线程的堆中资源没有释放造成的,而是我的线程对对象所占用的内存空间没有释放.
我跟踪了一下,线程的Destroy也没有被执行,类Thread的Free方法被调用了,但是该方法之前应该调用TMyThread.Destroy才对.

[ 本帖最后由 sunnyfairy 于 2011-1-5 13:28 编辑 ]
Top
zzzl (早安的空气)
版主
Rank: 7Rank: 7Rank: 7



UID 590
Digest Posts 0
Credits 399
Posts 199
点点分 399
Reading Access 100
Registered 2004-11-29
Status Offline
Post at 2011-1-5 22:46  Profile | Blog | P.M.  | QQ
同意passion的方法

在你的写法1里,虽然FreeOnTerminated := True;了,但没有调用thread.terminate,所以线程对象还是没有释放,就象passion说的那样。
在你的写法2里,说实话有点晕没耐心看下去了 ,另外你的WaitForSingleObject(Handle, 1);写法是什么意思呢?为什么不直接用sleep(1)?

其实如果你的线程在被干掉之前不需要什么必须的操作的话(比如保存文件),一个更简单的方法是不释放线程,操作系统会替你搞定。delphi的内存报告工具只是说进程自己没清理的内存,但这样每次关闭程序都要弹出个框框也太郁闷了,你可以这样写,还是分两种情况:
1,FreeOnTerminated := True;
在窗体的close事件里,直接写thread.free就完了,没有leak

2,FreeOnTerminated := False;
在窗体的close事件里,直接写
thread.Terminate;
while not thread.Finished do;
也是没有leak


另外前提是线程的execute里,要有出口,就象passion写的那样,如果是一个没出口的死循环,那你需要的是一个杀死线程的方法,而不是释放线程对象。
Top
sunnyfairy
新警察
Rank: 1



UID 57476
Digest Posts 0
Credits 34
Posts 12
点点分 34
Reading Access 10
Registered 2011-1-3
Status Offline
Post at 2011-1-12 10:33  Profile | Blog | P.M. 
其实我的第一种方法里,是有Thread.Terminate的,是在单元文件的FInit过程里.但是仍然有内存泄露问题.


其实我现在的一个现实问题就是:

我直接使用的是第一种方法,FreeOnTerminated := True;
while not Terminated do
begin
  //..
  Sleep(5分钟)
end;

最后单元的Finit节里Thread.Terminite.

原以为当进程退出时,程序不会马上退出.像Passion说的,不过实现是程序马上就退出了.

但造成的一个问题就是 内存泄露.

我不知道原因为是什么.
Top
zzzl (早安的空气)
版主
Rank: 7Rank: 7Rank: 7



UID 590
Digest Posts 0
Credits 399
Posts 199
点点分 399
Reading Access 100
Registered 2004-11-29
Status Offline
Post at 2011-1-12 16:34  Profile | Blog | P.M.  | QQ
你纠结的就是为什么进程不等待线程全部结束了再退出?

其实正常关闭程序,就是主线程函数返回了,这时windows的工作之一,就是回收其所有线程的内存。

看windows核心编程
Top
 




All times are GMT++8, the time now is 2024-5-15 02:19

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.007059 second(s), 7 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP