多线程操作数据库,在线程内创建ADO控件但线程结束后ADO控件不能被完全释放,运行过程中内存不断增加

时间:2022-09-18 18:40:53
多线程操作数据库,在线程内创建ADO控件但线程结束后ADO控件不能被完全释放,运行过程中内存不断增加,不知道是怎么回事,希望高手予以解决!
 我的线程代码如下:
type
  ShowSSdata = class(TThread)
  private
   b1,b2,b3,b4:integer;
   aa:integer;
   edits:Tedit;
   Conn: TADOConnection;
   AdoQuery_temp:TADOQuery;

    { Private declarations }
  protected
   procedure giveanser;
   procedure Execute; override;
 public
  a1:integer;
  a2:integer;
  a3:integer;
  a4:integer;

  constructor create(var a1_,a2_,a3_,a4_:integer;edv:Tedit);
  destructor Destroy;

  end;

implementation

uses Unit1;

{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure ShowSSdata.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ ShowSSdata }



constructor ShowSSdata.create(var a1_,a2_,a3_,a4_:integer;edv:Tedit);
begin
 CoInitialize(nil);

 inherited Create(false);
 FreeOnTerminate := true;

 try
  conn:=TADOconnection.Create(nil);
  AdoQuery_temp:=TAdoQuery.Create(nil);
 except
  conn.Free;
  AdoQuery_Temp.Free;
 end;
 edits:=edv;
end;

destructor ShowSSdata.Destroy;
begin

  conn.Free;
  AdoQuery_temp.Free;
  form1.memo1.Lines.Add('退出线程');
  Freeandnil(conn);
  Freeandnil(AdoQuery_temp);
  CoUnInitialize;
  inherited Destroy;
end;

procedure ShowSSdata.Execute;
var
 i:integer;
begin
 aa:=0;
 for i:=0 to 10 do
  begin
   if terminated then break;
   sleep(1);
   inc(aa,1);
   inc(form1.a1);
   inc(form1.a2);
   inc(form1.a3);
   inc(form1.a4);
   synchronize(giveanser);
  end;

  { Place thread code here }
end;

procedure ShowSSdata.giveanser;
begin
 with form1 do
  begin
   edit1.Text:=inttostr(a1);
   edit2.Text:=inttostr(a2);
   edit3.Text:=inttostr(a3);
   edit4.Text:=inttostr(a4);
   edits.Text:=inttostr(aa);
  end;
end;

end.

以上是我的代码,应该没有什么错误,当我把创建ADO控件的低码屏蔽后运行线程程序内存不会增加,加上之后内存一直在增长.不知道是什么原因?请高手指点迷津!

11 个解决方案

#1



最好不要用多线程建ADO控件..

会有很多意想不到的问题...

#2


你动态创建的ADO也得设置一下它的属性啊
比如连接属性

#3


还有 我觉得你同步的时候不光要同步Edit的操作
因为ADO也是一个控件对象 它在创建的时候 也需要同步的
不然线程就可能不安全了 也许就会出现你上面的原因
记住:只要是对可视话控件操作 都得要线程同步
本来ADO就有同步,异步的概念

#4


CoInitialize(nil); /CoUnInitialize; 
这个配对要放到线程的Execute过程当中,如果仅只是线程当中使用的ADO对象,最好在线程的Execute当中的"CoInitialize(nil); /CoUnInitialize; "配对中间进行创建、使用、销毁。

procedure TSomeThread.Execute;
begin
  CoInitialize(nil);
  try
    //Do something with OLE/COM
    ...
  finally
    CoUnInitialize;
  end;
end;

#5



destructor ShowSSdata.Destroy; 
begin 

  conn.Free; 
  AdoQuery_temp.Free; 
  form1.memo1.Lines.Add('退出线程'); 
  Freeandnil(conn); 
  Freeandnil(AdoQuery_temp); 
  CoUnInitialize; 
  inherited Destroy; 
end; 
这段代码竟然能不报错?

#6


建议楼主可以参考一下:
http://download.csdn.net/source/396131

#7


我只是说明一下这个原因,这个问题该如何解决?有没有人哪个同仁碰到过这个问题呢?感觉特别郁闷呀,倒底是怎么回事?什么原因造成的这个问题呢?请高手指点

#8


引用 7 楼 wxg666 的回复:
我只是说明一下这个原因,这个问题该如何解决?有没有人哪个同仁碰到过这个问题呢?感觉特别郁闷呀,倒底是怎么回事?什么原因造成的这个问题呢?请高手指点

大部分人碰到的,类似的情况,看4楼的方法可以解决.

#9


我在线程中只对ADO的QUERY控件进行查询并在进程中使用其查询的数据,并不显示其数据,这个还需要同步吗?如果同步的话,我将怎么写这个同步呢?

#10


引用 9 楼 wxg666 的回复:
我在线程中只对ADO的QUERY控件进行查询并在进程中使用其查询的数据,并不显示其数据,这个还需要同步吗?如果同步的话,我将怎么写这个同步呢?

不是同步的问题,而是操作COM,需要进行COM环境的初始化,否则在列集数据的时候,有可能会导致内存泄露.

#11


constructor ShowSSdata.create(var a1_,a2_,a3_,a4_:integer;edv:Tedit); 
begin 
CoInitialize(nil); 

inherited Create(false); 
FreeOnTerminate := true; 

try 
  conn:=TADOconnection.Create(nil); 
  AdoQuery_temp:=TAdoQuery.Create(nil); 
except 
  conn.Free; 
  AdoQuery_Temp.Free; 
end; 
edits:=edv; 
end; 
楼主是在这创建TADOconnection和TAdoQuery的,而这个方法是在主线程中执行的
虽然TADOconnection和TAdoQuery很有可能是在实际连接的时候才创建COM对象,但仍建议把它们放到Excute中去,同时在Excute中初始化套间完成之后再创建他们。

#1



最好不要用多线程建ADO控件..

会有很多意想不到的问题...

#2


你动态创建的ADO也得设置一下它的属性啊
比如连接属性

#3


还有 我觉得你同步的时候不光要同步Edit的操作
因为ADO也是一个控件对象 它在创建的时候 也需要同步的
不然线程就可能不安全了 也许就会出现你上面的原因
记住:只要是对可视话控件操作 都得要线程同步
本来ADO就有同步,异步的概念

#4


CoInitialize(nil); /CoUnInitialize; 
这个配对要放到线程的Execute过程当中,如果仅只是线程当中使用的ADO对象,最好在线程的Execute当中的"CoInitialize(nil); /CoUnInitialize; "配对中间进行创建、使用、销毁。

procedure TSomeThread.Execute;
begin
  CoInitialize(nil);
  try
    //Do something with OLE/COM
    ...
  finally
    CoUnInitialize;
  end;
end;

#5



destructor ShowSSdata.Destroy; 
begin 

  conn.Free; 
  AdoQuery_temp.Free; 
  form1.memo1.Lines.Add('退出线程'); 
  Freeandnil(conn); 
  Freeandnil(AdoQuery_temp); 
  CoUnInitialize; 
  inherited Destroy; 
end; 
这段代码竟然能不报错?

#6


建议楼主可以参考一下:
http://download.csdn.net/source/396131

#7


我只是说明一下这个原因,这个问题该如何解决?有没有人哪个同仁碰到过这个问题呢?感觉特别郁闷呀,倒底是怎么回事?什么原因造成的这个问题呢?请高手指点

#8


引用 7 楼 wxg666 的回复:
我只是说明一下这个原因,这个问题该如何解决?有没有人哪个同仁碰到过这个问题呢?感觉特别郁闷呀,倒底是怎么回事?什么原因造成的这个问题呢?请高手指点

大部分人碰到的,类似的情况,看4楼的方法可以解决.

#9


我在线程中只对ADO的QUERY控件进行查询并在进程中使用其查询的数据,并不显示其数据,这个还需要同步吗?如果同步的话,我将怎么写这个同步呢?

#10


引用 9 楼 wxg666 的回复:
我在线程中只对ADO的QUERY控件进行查询并在进程中使用其查询的数据,并不显示其数据,这个还需要同步吗?如果同步的话,我将怎么写这个同步呢?

不是同步的问题,而是操作COM,需要进行COM环境的初始化,否则在列集数据的时候,有可能会导致内存泄露.

#11


constructor ShowSSdata.create(var a1_,a2_,a3_,a4_:integer;edv:Tedit); 
begin 
CoInitialize(nil); 

inherited Create(false); 
FreeOnTerminate := true; 

try 
  conn:=TADOconnection.Create(nil); 
  AdoQuery_temp:=TAdoQuery.Create(nil); 
except 
  conn.Free; 
  AdoQuery_Temp.Free; 
end; 
edits:=edv; 
end; 
楼主是在这创建TADOconnection和TAdoQuery的,而这个方法是在主线程中执行的
虽然TADOconnection和TAdoQuery很有可能是在实际连接的时候才创建COM对象,但仍建议把它们放到Excute中去,同时在Excute中初始化套间完成之后再创建他们。