下面是我的连接池的代码,我比较简单,还没有做计时释放的工作。constructor TConnectionPools.Create; begin FConnList := TList.Create; FCriticalSection := TCriticalSection.Create; FTimeout := 5000; FMaxCount := 15; FSemaphore := CreateSemaphore(nil, FMaxCount, FMaxCount, nil);end;function TConnectionPools.CreateNewInstance: TADOConnection; var p: PRemoteConnection; begin Result := nil; FCriticalSection.Enter; try New(p); p.Connection := TADOConnection.Create(nil); p.Connection.ConnectionString := ConnectionString; p.Connection.LoginPrompt := False; try p.Connection.Open(DataBaseUser,DataBasePass); except p.Connection.Free; Dispose(p); Exit; end; p.InUse := True; FConnList.Add(p); Result := p.Connection; finally FCriticalSection.Leave; end; end;destructor TConnectionPools.Destroy; var i: Integer; begin FCriticalSection.Free; for i := 0 to FConnList.Count - 1 do begin PRemoteConnection(FConnList[i]).Connection.Free; Dispose(FConnList[i]); end; FConnList.Free; CloseHandle(FSemaphore); inherited Destroy; end;function TConnectionPools.GetLock(Index: Integer): Boolean; begin FCriticalSection.Enter; try Result := not PRemoteConnection(FConnList[Index]).InUse; if Result then PRemoteConnection(FConnList[Index]).InUse := True; finally FCriticalSection.Leave; end; end;function TConnectionPools.LockConnection: TADOConnection; var i: Integer; begin Result := nil; if WaitForSingleObject(FSemaphore, Timeout) = WAIT_FAILED then raise Exception.Create('服务器忙,请稍候再试'); for i := 0 to FConnList.Count - 1 do begin if GetLock(i) then begin Result := PRemoteConnection(FConnList[i]).Connection; Exit; end; end; if FConnList.Count < MaxCount then Result := CreateNewInstance; if Result = nil then { This shouldn't happen because of the sempahore locks } raise Exception.Create('Unable to lock Connection'); end;procedure TConnectionPools.ReleaseLock(Index: Integer; var Value: TADOConnection); begin FCriticalSection.Enter; try PRemoteConnection(FConnList[Index]).InUse := False; //Value := nil; ReleaseSemaphore(FSemaphore, 1, nil); finally FCriticalSection.Leave; end; end;procedure TConnectionPools.SetConnectionString(const Value: string); begin FConnectionString := Value; end;procedure TConnectionPools.SetDataBasePass(const Value: string); begin FDataBasePass := Value; end;procedure TConnectionPools.SetDataBaseUser(const Value: string); begin FDataBaseUser := Value; end;procedure TConnectionPools.UnlockConnection(var Value: TADOConnection); var i: Integer; begin for i := 0 to FConnList.Count - 1 do begin if Value = PRemoteConnection(FConnList[i]).Connection then begin ReleaseLock(i, Value); break; end; end; end;initialization ConnectionPools := TConnectionPools.Create; finalization ConnectionPools.Free; end. 这是下午弄的,唉,忙里偷闲,现在的公司是不想呆了,数据库弄得头大,天天老一涛,没劲
连接池 ??? 是什麼東西?
所谓的连接池
就是程式意义的池数据模块作为一个类
你当然可以创建它的多个实例
用来实现对数据库的连接建立一个活动列表和池列表
用临界区的同步方式对它们进行访问
本身就有DEMO
或者参考INDY的池实现方式
具体技术上不用我说了吧
简单
-------我只明白了最后两个字 ...
列一个数组,创建10个对象来访问数据库即可.有一个TPool的例子, 就在DEMO中, 和BDE没有关系.
MSSQL的确做了一些
甚至ADO驱动也提供了一个Seccion: TADOConnection
我不知你看过 COM+ 或 Midas 与之相关的概念没有?至于你要做连接池
那你自己开辟吧
一般封装在线程里
相对来说
这也是你是否必要创建池的一个标准(我认为)
http://community.csdn.net/Expert/topic/3452/3452115.xml?temp=1.339138E-03
Windows, Contnrs;
type
TCriticalSection = class(TObject)
protected
FHandle: Cardinal;
FQueue: TQueue;
FSection: TRTLCriticalSection;
FItemClass: TClass;
FCount: Integer;
FCapacity: Integer; procedure Enter;
procedure Leave;
public
constructor Create(ItemClass: TClass; Capacity: Integer);
destructor Destroy; override; procedure Push(Obj: TObject);
function Pop: TObject;
end;implementationuses SysUtils;{ TCriticalSection }constructor TCriticalSection.Create(ItemClass: TClass; Capacity: Integer);
begin
inherited Create;
InitializeCriticalSection(FSection);
FQueue := TQueue.Create;
FItemClass := ItemClass;
FCount := 0;
FCapacity := Capacity;
FHandle := CreateSemaphore(nil, 0, Capacity, nil);
end;destructor TCriticalSection.Destroy;
begin
FreeAndNil(FQueue);
DeleteCriticalSection(FSection);
CloseHandle(FHandle);
inherited Destroy;
end;procedure TCriticalSection.Enter;
begin
EnterCriticalSection(FSection);
end;procedure TCriticalSection.Leave;
begin
LeaveCriticalSection(FSection);
end;function TCriticalSection.Pop: TObject;
var
Return: Cardinal;
begin
Result := nil;
Return := WaitForSingleObject(FHandle, INFINITE);
if Return = WAIT_OBJECT_0 then
begin
Enter;
Result := FQueue.Pop;
Leave;
end;
end;procedure TCriticalSection.Push(Obj: TObject);
begin
if (not Assigned(Obj)) or (not (Obj is FItemClass)) then exit; try
Enter;
if FCount >= FCapacity then
Raise Exception.Create('池已满!')
else
begin
FQueue.Push(Obj);
Inc(FCount);
ReleaseSemaphore(FHandle, 1, nil);
end;
finally
Leave;
end;
end;end.
你可以放任何对象
包括你说的TADOConneciton或数据模块不知你明白否?
这本来就是简单的东西
不知你理解的那个DEMO没有?!
D的TQueue做的非常差劲
主要是效率低
你可以自己写个循环队列^_^
begin
FConnList := TList.Create;
FCriticalSection := TCriticalSection.Create;
FTimeout := 5000;
FMaxCount := 15;
FSemaphore := CreateSemaphore(nil, FMaxCount, FMaxCount, nil);end;function TConnectionPools.CreateNewInstance: TADOConnection;
var
p: PRemoteConnection;
begin
Result := nil;
FCriticalSection.Enter;
try
New(p);
p.Connection := TADOConnection.Create(nil);
p.Connection.ConnectionString := ConnectionString;
p.Connection.LoginPrompt := False;
try
p.Connection.Open(DataBaseUser,DataBasePass);
except
p.Connection.Free;
Dispose(p);
Exit;
end;
p.InUse := True;
FConnList.Add(p);
Result := p.Connection;
finally
FCriticalSection.Leave;
end;
end;destructor TConnectionPools.Destroy;
var
i: Integer;
begin
FCriticalSection.Free;
for i := 0 to FConnList.Count - 1 do
begin
PRemoteConnection(FConnList[i]).Connection.Free;
Dispose(FConnList[i]);
end;
FConnList.Free;
CloseHandle(FSemaphore);
inherited Destroy;
end;function TConnectionPools.GetLock(Index: Integer): Boolean;
begin
FCriticalSection.Enter;
try
Result := not PRemoteConnection(FConnList[Index]).InUse;
if Result then
PRemoteConnection(FConnList[Index]).InUse := True;
finally
FCriticalSection.Leave;
end;
end;function TConnectionPools.LockConnection: TADOConnection;
var
i: Integer;
begin
Result := nil;
if WaitForSingleObject(FSemaphore, Timeout) = WAIT_FAILED then
raise Exception.Create('服务器忙,请稍候再试');
for i := 0 to FConnList.Count - 1 do
begin
if GetLock(i) then
begin
Result := PRemoteConnection(FConnList[i]).Connection;
Exit;
end;
end;
if FConnList.Count < MaxCount then
Result := CreateNewInstance;
if Result = nil then { This shouldn't happen because of the sempahore locks }
raise Exception.Create('Unable to lock Connection');
end;procedure TConnectionPools.ReleaseLock(Index: Integer;
var Value: TADOConnection);
begin
FCriticalSection.Enter;
try
PRemoteConnection(FConnList[Index]).InUse := False;
//Value := nil;
ReleaseSemaphore(FSemaphore, 1, nil);
finally
FCriticalSection.Leave;
end;
end;procedure TConnectionPools.SetConnectionString(const Value: string);
begin
FConnectionString := Value;
end;procedure TConnectionPools.SetDataBasePass(const Value: string);
begin
FDataBasePass := Value;
end;procedure TConnectionPools.SetDataBaseUser(const Value: string);
begin
FDataBaseUser := Value;
end;procedure TConnectionPools.UnlockConnection(var Value: TADOConnection);
var
i: Integer;
begin
for i := 0 to FConnList.Count - 1 do
begin
if Value = PRemoteConnection(FConnList[i]).Connection then
begin
ReleaseLock(i, Value);
break;
end;
end;
end;initialization
ConnectionPools := TConnectionPools.Create;
finalization
ConnectionPools.Free;
end.
这是下午弄的,唉,忙里偷闲,现在的公司是不想呆了,数据库弄得头大,天天老一涛,没劲
拜托你能不能将池抽象出来?
你这个和DEMO有什么区别?
同样可以实现动态创建对象啊
那么我们再展开讨论一下
^_^我们知道
COM/DCOM/COM+在开发分布式多层系统时效率非常的低
但是不要错怪了MIDAS或COM+,或者Delphi本身
主要原因还是程序员自己的问题要想开发一个高效的分布式系统
李维的书讲了很多
但是很多朋友看完后仍然不懂,或不知具体如何做要想得到高效率的系统
必须能并行执行客户端的请求
也就是多线程在线程模型中
有Single/Apartment/Free/Both/N...?什么的
一般来说,我们推荐使用Automation模型
但是,当我们建立此类型的DCOM/COM+对象时
D并不达到我们想要的目的此时我们回到上面的例程
恰恰演示了Automation线程是如何建立、使用的
这样
就可以同时处理多客户的并行访问,提高了系统的效率在纯应用程序中
要实现它
必须自己来Marshaling
如何Marshaling?
就是:进入COM前CoInitialize(nil);离开COM前CoUninitialize;其实
只要李维讲POOLING的讲解放在线程模型的后面
我想大家就一下子明白了再则
如果POOLING这个DEMO能将池抽象出来
这POOLING例程可能是一个完美的Automation模型的具体应用
Automation -》 Apartment
就是:进入COM前CoInitialize(nil);离开COM前CoUninitialize;这里是错误的
谢谢哈欠的指正
呵呵