一个简单的问题(先到现的) (50分)

  • 主题发起人 主题发起人 黑狼
  • 开始时间 开始时间

黑狼

Unregistered / Unconfirmed
GUEST, unregistred user!
在delphi编程中我们遵循这样一条原则,"不用的对象应该及时从内存清除掉."
但是,我在处理多线程的程序时,发现线程对象用一种方法不能自动从内存中清除.如以下源代码:
procedure tmythread.execute;
var
i:integer;
begin
freeonterminate:=true;
for i:=0 to 10000do
do
SOMETHING....;
end;
执行完以上语句后,这个多线程对象应该被freeonterminate:=true从内存中清除掉.
但是,当我用以下源代码判断时,却发现不是这样的.
var
mythread:tmythread;
procedure TForm1.Button1Click(Sender: TObject);
begin
if assigned(mythread) then
messagebox(0,'多线程对象清除成功!','提示!',mb_ok)
else
messagebox(0,'多线程对象清除失败!','提示!',mb_ok);
end;
结果当然是"多线程对象清除失败!"
<<注:"freeonterminate:=true是一些delphi书中介绍的清除多线程对象的方法".>>
当我用mythread.free时不是出现错误提示:"非法句柄",就是程序死掉.WHY???????
而我最后用以下源代码实现清除多线程对象,在execute最后加了一句free.
procedure tmythread.execute;
var
i:integer;
begin
freeonterminate:=true;
for i:=0 to 10000do
do
SOMETHING....;
free;
end;
问题是解决了,但问题我还没搞清楚,矛盾吧!
希望各位高手帮忙告诉我一下这是怎么什么原因!

 
mythread虽然释放了,但是不会被自动置为nil
所以assigned(mythread)当然为真了
 
//mythread虽然释放了,但是不会被自动置为nil
//所以assigned(mythread)当然为真了
妙兔无花 的解释是正确的。
我接着讲吧,提供一个解决的办法:
你在线程里面当然没有办法把自己置空了,只有在主窗口里面执行这一操作。
那么在什么时候呢?不知道,于是只有通过发送消息的方法。
当线程要释放的时候,向主窗口发送消息,主窗口收到消息过后就将其置空。
因此你需要自己定义一条消息:
const
WM_ThreadFree = WM_User + 123;
destructor tmythread.Destroy;
begin
PostMessage(Form1.Handle, WM_ThreadFree, 0, 0);
// 释放的时候发送消息给主窗口
inherited;
end;

然后在主窗口里面截获该消息:
type
TForm1 = class(TForm)
....
protected
procedure WMThreadFree(var Msg: TMessage);
message WM_ThreadFree;
...
procedure TForm1.WMThreadFree(var Msg: TMessage);
begin
Sleep(100);
// 稍微等一下,确保线程已经被完全释放
mythread := nil;
// 置空,这样你待会儿判断 Assigned(mythread) 的时候就 False 了
end;
 
to beta:
双保险
if mythread.terminated then
mythread:=nil;
或者在Application.OnIdle里面
if Assigned(mythread) then
if mythread.terminated then
mythread:=nil;
 
我想应该这样理解,
一、mythread是指向线程对象的指针,可理解成指向对象的变量
二、线程对象终止,是线程对象的实例终止,
三、指向线程对象的指针(是个一内存地址的值),它还有值
四、这个指针由那个创建,就应由那一个将指针值赋为 Nil
五、Delphi的标准代码
O:=Object.Create;
O.Free //释放O指针指向的对象
O:=nil //将指针对象释放
应该说Delphi的所有对象都应这样处理,
要不,就会有内存泄漏.
六、一般情况用以下语句总是对的
if mythread.terminated then
mythread:=nil;

七、对象不能释放自己,只能由创建他的父对象例程释放
消息机制也是通知mythread 的父对象:Form1释放mythread
 
to 妙兔无花:
//双保险 if mythread.terminated then
mythread:=nil;
要是 mythread 都已经释放了,你还能 mythread.terminated?[:)]
所以只有单保险:)
 
to beta
嗯,我忘了他是freeonterminate了
如果不是freeonterminate,可以在结束execute之后
if mythread.terminated then
freeandnil(mythread);
 
嗯,也是:)
 
多人接受答案了。
 
后退
顶部