关于多线程和内存的释放问题(150分)

  • 主题发起人 主题发起人 xfeiffer
  • 开始时间 开始时间
X

xfeiffer

Unregistered / Unconfirmed
GUEST, unregistred user!
先把我的线程弄出来吧:
线程中用到的结构体
PMsgList=^TMsgList;
//消息机制
TMsgList=record
Style:Integer;
//消息类别:0普通消息;1连接;2断开
Content:Array[0..9999]of Byte;
//消息内容
Length:Integer;
//消息长度
Thread:Pointer;
//Peer的Thread
end;
声明:
TManageMessageThread=class(TThread)
private
procedure HandleMessage;
//一些procedure或者function
public
myMessage:PMsgList;
myThread:TIdPeerThread;
myQuery:TADOQuery;
constructor Create(AStyle:Boolean;AQuery:TADOQuery;AMessage:PMsgList);overload;
procedure Execute;
override;
procedure Terminate;
procedure HandleMessage;
end;
以下是实现方法:
构造方法

constructor TManageMessageThread.Create(AStyle:Boolean;AQuery:TADOQuery;AMessage:PMsgList);
begin

CoInitialize(nil);//线程种要引用ActiveX控件
inherited Create(AStyle);
FreeOnTerminate:=true;//线程执行结束后自动释放
myQuery:=AQuery;
myQuery.Close;
myMessage:=AMessage;
myThread:=AMessage.Thread;//TIdPeerThread
end;
procedure TManageMessageThread.Execute;
begin

Synchronize(HandleMessage);//同步执行线程种的数据处理过程
[red]//WaitFor;
不知道在这个地方用这句话是否可以起到等待线程结束之后才推出临界区[/red]
end;
procedure TManageMessageThread.Terminate;
begin

myQuery.Close;
myQuery.Free;//释放线程中的ADO控件
myThread.Free;
FreeMem(myMessage);//释放指针,传入的AMessage是用GetMem来获取的,所以用FreeMem
CoUnInitialize;//释放ActiveX控件
inherited;
end;

问题:
现在线程执行没有问题,但我觉得线程执行完毕之后释放其占用的内存空间的时候有问题,只需要2天时间必定因为内存不足而死机,我查了N多的资料都说那个FreeOnTerminate:=true;可以释放,但我的为什么不能释放呢?
[red]请各位大侠帮帮忙,谢谢!![/red]
 
结构有点儿乱,为什么QueryADO要这么传进来而不是在线程里自己创建自己销毁?为什么消息队列也是这么传进来?为什么是在Terminate方法中释放对象?你调用了Terminate方法吗?Terminate是线程的调度者为了提前中止线程而提供的一个方法,而且你在execute函数里并没有进行循环,无从判断Terminated标志,所以这个函数实际上是无意义的。
你给这个类重载一个Destroy试试,在Destroy里释放,按照你的写法线程执行完毕后是会自动销毁的,但你却没有在线程自身销毁的时候没有把你想销毁的东西销毁掉。
 
依照你说的,那么那个FreeOnTerminate根本就不起作用了?
那FreeOnTerminate究竟是扮演的什么角色?必须要调用Terminate才能FreeOnTerminate还是当其运行结束时销毁?
 
FreeOnTerminate:=true;放在Execute;试试。我就放这里的。但是没有试过2天
 
FreeOnTerminate := True的意思,是当线程执行完毕后是否自动释放。
这个属性设置成True或False只在于是否需要你显式地调用FreeAndNil(YourThread)。
你的问题不在于线程有没有被释放,而是下面这些语句没有被执行到:
myQuery.Close;
myQuery.Free;//释放线程中的ADO控件
myThread.Free;
FreeMem(myMessage);
 
Wolfding说的没没错,应该把Terminate中的语句放入destroy中,或者放入事件onterminate的处理函数中。
tthread中的terminate函数只是设置线程的结束标识(terminated)为true。
 
OK,确实可以了,我跟踪线程的数量和进程所占用的内存数量,可以看到线程每次创建、销毁时可以看到计数器的变化,而且内存占用也跟以前很不一样,虽然有一些在慢慢增加,但很慢。
 
增加了Destory的重载,在里面释放创建线程时创建的所有控件,ADO也在线程里面自己创建然后结束时自动销毁,但消息必须得这样通过参数传进去。临界区修改在创建线程时进入,销毁时退出(以前是在主线程里准备创建线程的时候进入,线程resume之后再退出,好像运行起来也没有多大问题,能起到同步的作用),这样运行起来也没有问题了。
谢谢!!
 
后退
顶部