TIdTCPServer和多线程的问题(200分)

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

xfeiffer

Unregistered / Unconfirmed
GUEST, unregistred user!
现在正在做一个东西,用TIdTCPServer来做的服务器,客户端很多,目前的思路是Server打开之后接纳每一个客户端发送的所有信息,然后将数据分包,再存入SQL Server数据库中,Server接收客户端的连接、断开、数据处理都是用的多线程来实现,现在的问题是所有的功能都能实现,但程序所占用的内存空间却直线上升,在我的线程声明里面已经把所有的Object都释放掉了,但为什么内存还在上升呢?请大家帮忙看一下

线程声明:
PMsgList=^TMsgList; //消息机制
TMsgList=record
Content:Array[0..9999]of Byte; //消息内容
Length:Integer; //消息长度
end;

TManageMessageThread=class(TThread)
private
myMessage:PMsgList; //这是一个传入的消息,也就是客户端发送的数据
myThread:TIdPeerThread;
myQuery:TADOQuery;
procedure HandleMessage;
..... //其他过程
public
constructor Create(AStyle:Boolean;AMessage:PMsgList;AThread:TIdPeerThread);overload;
destructor Destroy; override;
protected
procedure Execute; override;
end;

实现:
constructor TManageMessageThread.Create(AStyle:Boolean;AMessage:PMsgList;AThread:TIdPeerThread);
begin
inherited Create(AStyle);
EnterCriticalSection(CS); //创建线程时进入临界区
CoInitialize(nil);
FreeOnTerminate:=true;
myQuery:=TADOQuery.Create(nil);
myQuery.Close;
myQuery.Connection:=FormMain.ADOConn;
myMessage:=AMessage;
myThread:=AThread;
//FreeAndNil(Self);
end;

destructor TManageMessageThread.Destroy;
begin
myThread:=nil;
myThread.Free;
FreeMem(myMessage);
myQuery.Close;
myQuery:=nil;
myQuery.Free;
CoUnInitialize;
LeaveCriticalSection(CS); //执行完毕后退出临界区
inherited Destroy;
end;

procedure TManageMessageThread.Execute;
begin
try
Synchronize(HandleMessage);
finally
free;
end;
end;

procedure TManageMessageThread.HandleMessage;
begin
//处理数据,里面有涉及到数据库的查询和更新操作
end;

问题:
[red]现在的问题我觉得好像在数据库查询或更新之后的RecordSet数据集没有释放,但看了Delphi的帮助文档,里面说用Close就能关闭(我自己也测试过,用ADO从数据库中取了17万条数据之后测试程序占用的内存约50M,调用Close之后内存降到10M左右,测试程序初始化时占用的内存约4M左右),这说明能释放数据集所占用的空间,而且我也在线程中的每个涉及到数据库操作的过程的最后调用了Close来释放,为了保险在线程Destroy的时候也Close了,但实际上运行起来的时候内存没有释放(Server接收到数据之后如果不调用线程处理的话内存使用几乎没有变化,但如果调用线程处理了的话,内存占用就上升很快,这说明这个线程有问题),该如何来处理这个线程的释放问题呢?大家帮帮忙……高分相送:)[/red]
 
在这边加入下面的语句看看
procedure TManageMessageThread.Execute;
begin
try
Synchronize(HandleMessage);
sleep(1000);//增加这条语句
finally
free;
end;
end;
还有在数据插入的时候最好是用动态创建。最后Free掉。
 
Synchronize造成的
另外,没看出你的临界区是要保护什么?
还有execute方法中的free好像没必要
 
临界区保护的是数据库访问的连接。
HandleMessage里面有涉及到主线程,比如要在Memo里面显示处理的结果等等这些,Delphi帮助文档里面不是都说需要这样的吗?
 
又是临街区又是Synchronize,那你的这些线程能并发运行吗?
建议你在子线程中单独建立connection连接数据库,去掉临界区。
关于Synchronize,只需要把涉及主线程的部分Synchronize,而不是全部Synchronize,这样全部都在主线程中执行,还开子线程有什么用?
 
按照maze说的改写了程序,但内存还是一直上升,如果我收到包之后就丢掉,不处理的话内存不增加,如果用创建线程但也不处理的话(Execute过程里的都注释掉),内存会一点一点的增加(说明线程实际没有释放掉或者没有释放干净,好像是16K左右的增加),如果线程处理数据的话内存增大的更快,增长幅度不等。
 
[:D][:D][:D]又一个朋友遇到这个问题。容易解决
在Execute 加上下面代码
FreeOnTerminate:=true;
 
FreeOnTerminate:=true;加在Execute里面会也不行
 
哈哈,终于自己搞定了,原来在我的Destroy里面用
myQuery:=nil;
myQuery.Free;
搞的怪,我把这个去掉,然后用FreeAndNil(myQuery);就释放掉了。(呵呵,看了TADOQuery的Destroy方法中Free掉SQL的方法)
现在程序运行起来内存占用增长幅度可以说没有了。
 
后退
顶部