我在线程中建立数据库连接,然后在其中释放。但是在数据库的sql Profiler中却看到线程执行完毕后还要等待一段时间,才看到连接与数据库断开。如果连续建100个线程的话,则数据库连接失败(此属正常,数据库连接不充许太多)。要怎样让数据库连接立即释放。代码如下:unit Thread;interfaceuses
  Classes,ADODB,sysUtils;type
  TSendDataThread = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
  public
    Tel,Data,ConnectionString:string;
  end;procedure SendData(Const Tel,Data:string);
  
implementationuses pub, CommProtocol;procedure TSendDataThread.Execute;
var
  i:integer;
  ds:TADODataSet;
  cp:TCommPack;
  sql,UserID,GroupID:string;
begin
  self.FreeOnTerminate:=true;
  ds:=TADODataSet.Create(nil);
  try
    try
      ds.ConnectionString:=ConnectionString;
      ds.CommandText:='select CarGroupID from CarInfo where Phone='''+Tel+'''';
      ds.Open;
      GroupID:=ds.Fields[0].AsString; 
      sql:='select UserName from tUser where (CarGroupID in (select ID from '
        +' GetChild('''+GroupID+''')) and subString(UserType,1,1)=''1'') ';
      ds.Close;
      ds.CommandText:=sql;
      ds.Open;
    except
      ds.Free;
      exit;
    end;
     //操作数据
  finally
    ds.Free;
  end;
end;procedure SendData(Const Tel,Data:string);
var
  Thread:TSendDataThread;
begin
  Thread:=TSendDataThread.Create(true);
  Thread.Tel:=Tel;
  Thread.Data:=Data;
  Thread.ConnectionString:=pub.ConnectionString;
  Thread.Resume;
end;end.
我如果运行下面的程序则报连接错误。在数据库里也可看到很多连接没有释放。
for i:=0 to 100 do
  SendData(tel,data);

解决方案 »

  1.   

    unit QuerThrd;interfaceuses
      ADODB, Classes;type
      TQueryThreadk = class(TThread)
      private
      fADOQuery: TADOQuery;
        { Private declarations }
      protected
        procedure Execute; override;
      public
         constructor Create(suspended:boolean;AdoQuery:TadoQuery);
      end;
    implementation{ Important: Methods and properties of objects in VCL can only be used in a
      method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure TQueryThreadk.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end; }{ TQueryThreadk }constructor TQueryThreadk.Create(suspended: boolean; AdoQuery: TadoQuery);
    begin
       inherited Create(suspended);
       fADOQuery:=AdoQuery;
       FreeOnTerminate:=True;
    end;procedure TQueryThreadk.Execute;
    begin
      { Place thread code here }
       fADOQuery.Open ;
    end;procedure SendData(Const Tel,Data:string);
    var
      Thread:TSendDataThread;
    begin
     for i:=1 to 100 do  begin
         TQueryThreadk.Create(False,AdoQuery1);
     end;
    end;end.
      

  2.   

    To:RamjetZhang(万花从中一点红,玉树临风王小桃是也) ( ) 
    如果不开一个连接的话,怎么作呢,要考虑到线程安全啊
      

  3.   


    你的问题我也见过,我是这样解决的 :
    uses ComObj;coInitFlags = 8;
      

  4.   

    你的问题我也见过,我是这样解决的 :
    uses ComObj;initialization
      CoInitFlags := 8;
      

  5.   

    to 楼主:
    向你这种情况,3个选择
    1. 老老实实用单个数据库连接来解决,自己注意线程安全;
    2. 自己开线程维护数据库连接,但貌似就你的所述,开100个工作者线程,我看不出哪个实用的(投入生产应用)的程序会开那么多线程的,一般建议十几个为宜,多了只会导致性能下降,100个就完全是作为测试(主要是压力测试)应用了;
    3. 启用数据库连接池,由池来维护数据库连接;需要的时候创建连接,用完立刻关掉送回池中,并且建议连接对象在stack上创建(而不是作为类的field创建)
    p.s.貌似你的代码里并没有显式地关闭连接;要想“让数据库连接立即释放”,建议数据库连接字符串里加上"pooling = false",禁用连接池,否则默认状态(启用池)下关掉的连接并不被关闭,而是送入池中待命.
      

  6.   

    Thread.Resume方法:当线程对象处于暂停状态时,调用此方法可以使线程恢复运行。
    用Thread.Terminate;
      

  7.   

    TO: delphi1234567(我要学DELPHI)
    不知CoInitFlags:=8是不什么意思,小弟才浅,还望老兄多多指教
    uses ComObj;initialization
      CoInitFlags := 8;
      

  8.   

    To: RamjetZhang(万花从中一点红,玉树临风王小桃是也) 
    其实我开100个线程只是为了作处理发送数据,如果来的数据很快的话,就有可能,我现在只要在线程结束时就立即关了连接释放资源。我在主线程中测试只要ADOConnection.free则数据库连接就立即释放了,但在线线程中不是,它要等待一段时间才释放连接(大约一两分钟)。你说在数据库连接字符串中加上"pooling = false",禁用连接池,我试试。
      

  9.   

    在 DELPHI 的帮助中找到如下解释:
    Specifies the level of threading support requested for a COM server .EXE.UnitComObjCategoryCOM utilitiesDelphi syntaxvar CoInitFlags: Integer = -1;DescriptionCoInitFlags controls the way COM is initialized for threading support. This variable only affects executables (.EXEs), not in-process servers (.DLLs and .OCXs).
    Typically, code to initialize the level of threading support is added automatically by the wizard that creates the COM object in your application. In applications containing multiple COM objects, COM is initialized for the highest level of support, where single threading is lowest and free threading is highest. To manually set the level of COM threading support, assign a value to CoInitFlags in the program抯 main source file before the call to Application.Initialize.The following table lists the constants (defined in the ActiveX unit) that can be or抏d together to create a value for CoInitFlags.Constant Value MeaningCOINIT_MULTITHREADED 0 COM calls objects on any thread (free threading)
    COINIT_APARTMENTTHREADED 2 Each object has its own thread (apartment model)
    COINIT_DISABLE_OLE1DDE 4 Don't use DDE for Ole1 support.
    COINIT_SPEED_OVER_MEMORY 8 Optimize for speed rather than memory.The value of CoInitFlags is -1 for single threading.
      

  10.   

    TO: delphi1234567(我要学DELPHI)
    我试过了加入下面行也不行,你在运行时在sql查询分器里运行 sp_who 语句看一下就知道了运行后多了很多连接,大约过一分钟后就释放了。我用的是sql server 2000initialization
      CoInitFlags := 8;
      

  11.   

    To: RamjetZhang(万花从中一点红,玉树临风王小桃是也) 
    我试过了在连接串里加入pooling=false也不行,你在运行时在sql查询分器里运行 sp_who 语句看一下就知道了运行后多了很多连接,大约过一分钟后就释放了。我用的是sql server 2000