我在线程中建立数据库连接,然后在其中释放。但是在数据库的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);
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);
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.
如果不开一个连接的话,怎么作呢,要考虑到线程安全啊
你的问题我也见过,我是这样解决的 :
uses ComObj;coInitFlags = 8;
uses ComObj;initialization
CoInitFlags := 8;
向你这种情况,3个选择
1. 老老实实用单个数据库连接来解决,自己注意线程安全;
2. 自己开线程维护数据库连接,但貌似就你的所述,开100个工作者线程,我看不出哪个实用的(投入生产应用)的程序会开那么多线程的,一般建议十几个为宜,多了只会导致性能下降,100个就完全是作为测试(主要是压力测试)应用了;
3. 启用数据库连接池,由池来维护数据库连接;需要的时候创建连接,用完立刻关掉送回池中,并且建议连接对象在stack上创建(而不是作为类的field创建)
p.s.貌似你的代码里并没有显式地关闭连接;要想“让数据库连接立即释放”,建议数据库连接字符串里加上"pooling = false",禁用连接池,否则默认状态(启用池)下关掉的连接并不被关闭,而是送入池中待命.
用Thread.Terminate;
不知CoInitFlags:=8是不什么意思,小弟才浅,还望老兄多多指教
uses ComObj;initialization
CoInitFlags := 8;
其实我开100个线程只是为了作处理发送数据,如果来的数据很快的话,就有可能,我现在只要在线程结束时就立即关了连接释放资源。我在主线程中测试只要ADOConnection.free则数据库连接就立即释放了,但在线线程中不是,它要等待一段时间才释放连接(大约一两分钟)。你说在数据库连接字符串中加上"pooling = false",禁用连接池,我试试。
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.
我试过了加入下面行也不行,你在运行时在sql查询分器里运行 sp_who 语句看一下就知道了运行后多了很多连接,大约过一分钟后就释放了。我用的是sql server 2000initialization
CoInitFlags := 8;
我试过了在连接串里加入pooling=false也不行,你在运行时在sql查询分器里运行 sp_who 语句看一下就知道了运行后多了很多连接,大约过一分钟后就释放了。我用的是sql server 2000