CnPack Forum » CnPack IDE 专家包(CnWizards) » 请教一个多线程退出的问题.


2011-1-3 12:02 sunnyfairy
请教一个多线程退出的问题.

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

关于多线程终止的问题.

在多线程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通知吗?

[[i] 本帖最后由 sunnyfairy 于 2011-1-3 12:06 编辑 [/i]]

2011-1-3 19:25 Passion
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;

2011-1-5 13:22 sunnyfairy
多次等待是个好方法.
不过我的第1个问题里面为什么那样写的话,内存工具会报内存泄漏?

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

[[i] 本帖最后由 sunnyfairy 于 2011-1-5 13:28 编辑 [/i]]

2011-1-5 22:46 zzzl
同意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写的那样,如果是一个没出口的死循环,那你需要的是一个杀死线程的方法,而不是释放线程对象。

2011-1-12 10:33 sunnyfairy
其实我的第一种方法里,是有Thread.Terminate的,是在单元文件的FInit过程里.但是仍然有内存泄露问题.


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

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

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

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

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

我不知道原因为是什么.

2011-1-12 16:34 zzzl
你纠结的就是为什么进程不等待线程全部结束了再退出?

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

看windows核心编程

页: [1]


Powered by Discuz! Archiver 5.0.0  © 2001-2006 Comsenz Inc.