好久没用Delphi了,不过还是觉得很有感情。呵
大家节日快乐!不知道这个时候发帖子会不会都出去旅游了,希望还有像我一样在前线的兄弟。回到问题:
我现在想在DLL中通过内存映射的方式共享ADO连接(会有多个,所以我用数组存储他们),当作一个连接池(自己随便编的),引用的应用程序首先查看内存是否有已经建立的连接,有这返回,没有则建立一个新的。我当前是分两步测试,创建连接,和取连接。
第一种情况:
创建和使用都在同一个应用程序中没有问题。第二种情况:
调用DLL的主程序打开两个,一个创建链接,另外一个引用这个连接,发现问题来了,记录中的其他两个简单类型的变量FDBNameSet,FConnectionCount没有问题,能正常读出,说明内存映射基本正常,但是对象FDBConnSet是TADOConnection类型的就有问题,他也有值,不为空,但是就是读出来就是有问题,见下面红色字体部分。
写得有点多,郁闷了两天,网上搜了好久没解决,所以还请您多担待一下,把它读完。
unit ConnectionPoolUnit;interfaceuses Windows,ADODB,Dialogs,SysUtils;Const
REQUEST_TIMEOUT = 1000;
//according to sb's comment, system will NOT allocate memory for the one defined in type section
COUNT_MAX_CONNECTION = 50;
NAME_MEM_MAP = 'Inter Application Memory Map File';
NAME_MUTEX = 'Inter Application Mutex';type
TConnectionPool=record
FDBNameSet:array[0..COUNT_MAX_CONNECTION] of PChar;
FDBConnSet:array[0..COUNT_MAX_CONNECTION] of TADOConnection;
FConnectionCount:Integer;
end;
PConnectionPool=^TConnectionPool;var
pConnPool:PConnectionPool;
hMapping: THandle;
hMapMutex: THandle;implementation{-Biz logic===================================================================-}procedure CreateAConnection(aDBName:PChar);stdcall;
var
adoConn:TADOConnection;
i_ConnCount:Integer;
begin
adoConn:=TADOConnection.Create(nil);
adoConn.LoginPrompt:=false;
adoConn.ConnectionString:='FILE NAME=X.udl'; i_ConnCount:=pConnPool^.FConnectionCount;
if i_ConnCount>10000 then i_ConnCount:=0;
if i_ConnCount>=COUNT_MAX_CONNECTION then
begin
ShowMessage('The connection count exceeds max setting value.');
exit;
end; pConnPool^.FDBNameSet[i_ConnCount]:=aDBName;
pConnPool^.FDBConnSet[i_ConnCount]:=adoConn;
Inc(i_ConnCount);
pConnPool^.FConnectionCount:=i_ConnCount; //adoConn.Free;
end;function RequestConnectionByRPC(aDBName:PChar):TADOConnection;stdcall;
begin
result:=nil;
end;function GetConnectionFromPool(aDBName:PChar):TADOConnection;stdcall;
var
i:Integer;
begin
result:=nil;
if pConnPool=nil then
begin
ShowMessage('No connection pool created.');
exit;
end; for i:=0 to pConnPool^.FConnectionCount-1 do
begin
if String(aDBName) = String(pConnPool^.FDBNameSet[i]) then
begin
result:=pConnPool^.FDBConnSet[i]; //一个进程的时候没有问题,当另外一个进程掉的时候这句有问题,但是pConnPool^记录里其他两字段的值正常。
end;
end;
end;function AllocateConnection(aDBName:PChar):TADOConnection;stdcall;
begin
result:=GetConnectionFromPool(aDBName); if result=nil then
begin
result:=RequestConnectionByRPC(aDBName);
end; if result=nil then ShowMessage('No database connection be created.');
end;{-Biz logic===================================================================-}
{-Mem Map=====================================================================-}
procedure CloseMemMap;
begin
if pConnPool <> nil then
UnMapViewOfFile(pConnPool);
if hMapping <> 0 then
CloseHandle(hMapping);
end;function LockMemMap: Boolean;
begin
Result := true;
hMapMutex := CreateMutex(nil, false, NAME_MUTEX);
if hMapMutex = 0 then
begin
ShowMessage('Failed to create a Map Mutex.');
Result := false;
end else
begin
if WaitForSingleObject(hMapMutex, REQUEST_TIMEOUT) = WAIT_FAILED then
begin
ShowMessage('The Map Mutex can NOT be locked.');
Result := false;
end;
end;
end;procedure UnlockMemMap;
begin
ReleaseMutex(hMapMutex);
CloseHandle(hMapMutex);
end;function OpenMemMap:boolean;
begin
result:=false;
hMapping:=OpenFileMapping(FILE_MAP_WRITE,false,NAME_MEM_MAP);
if hMapping=0 then
begin
hMapping := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
SizeOf(TConnectionPool), NAME_MEM_MAP);
if (hMapping = 0) then
begin
ShowMessage('Failed to create map file.');
exit;
end;
end; pConnPool := PConnectionPool(MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0));
if pConnPool = nil then
begin
CloseHandle(hMapping);
ShowMessage('The Memory Map can NOT be viewed.');
exit;
end; result:=true;
end;
{-Mem Map=====================================================================-}
exports
CreateAConnection, AllocateConnection;initialization
OpenMemMap;
LockMemMap;finalization
CloseMemMap;
UnlockMemMap;end.
大家节日快乐!不知道这个时候发帖子会不会都出去旅游了,希望还有像我一样在前线的兄弟。回到问题:
我现在想在DLL中通过内存映射的方式共享ADO连接(会有多个,所以我用数组存储他们),当作一个连接池(自己随便编的),引用的应用程序首先查看内存是否有已经建立的连接,有这返回,没有则建立一个新的。我当前是分两步测试,创建连接,和取连接。
第一种情况:
创建和使用都在同一个应用程序中没有问题。第二种情况:
调用DLL的主程序打开两个,一个创建链接,另外一个引用这个连接,发现问题来了,记录中的其他两个简单类型的变量FDBNameSet,FConnectionCount没有问题,能正常读出,说明内存映射基本正常,但是对象FDBConnSet是TADOConnection类型的就有问题,他也有值,不为空,但是就是读出来就是有问题,见下面红色字体部分。
写得有点多,郁闷了两天,网上搜了好久没解决,所以还请您多担待一下,把它读完。
unit ConnectionPoolUnit;interfaceuses Windows,ADODB,Dialogs,SysUtils;Const
REQUEST_TIMEOUT = 1000;
//according to sb's comment, system will NOT allocate memory for the one defined in type section
COUNT_MAX_CONNECTION = 50;
NAME_MEM_MAP = 'Inter Application Memory Map File';
NAME_MUTEX = 'Inter Application Mutex';type
TConnectionPool=record
FDBNameSet:array[0..COUNT_MAX_CONNECTION] of PChar;
FDBConnSet:array[0..COUNT_MAX_CONNECTION] of TADOConnection;
FConnectionCount:Integer;
end;
PConnectionPool=^TConnectionPool;var
pConnPool:PConnectionPool;
hMapping: THandle;
hMapMutex: THandle;implementation{-Biz logic===================================================================-}procedure CreateAConnection(aDBName:PChar);stdcall;
var
adoConn:TADOConnection;
i_ConnCount:Integer;
begin
adoConn:=TADOConnection.Create(nil);
adoConn.LoginPrompt:=false;
adoConn.ConnectionString:='FILE NAME=X.udl'; i_ConnCount:=pConnPool^.FConnectionCount;
if i_ConnCount>10000 then i_ConnCount:=0;
if i_ConnCount>=COUNT_MAX_CONNECTION then
begin
ShowMessage('The connection count exceeds max setting value.');
exit;
end; pConnPool^.FDBNameSet[i_ConnCount]:=aDBName;
pConnPool^.FDBConnSet[i_ConnCount]:=adoConn;
Inc(i_ConnCount);
pConnPool^.FConnectionCount:=i_ConnCount; //adoConn.Free;
end;function RequestConnectionByRPC(aDBName:PChar):TADOConnection;stdcall;
begin
result:=nil;
end;function GetConnectionFromPool(aDBName:PChar):TADOConnection;stdcall;
var
i:Integer;
begin
result:=nil;
if pConnPool=nil then
begin
ShowMessage('No connection pool created.');
exit;
end; for i:=0 to pConnPool^.FConnectionCount-1 do
begin
if String(aDBName) = String(pConnPool^.FDBNameSet[i]) then
begin
result:=pConnPool^.FDBConnSet[i]; //一个进程的时候没有问题,当另外一个进程掉的时候这句有问题,但是pConnPool^记录里其他两字段的值正常。
end;
end;
end;function AllocateConnection(aDBName:PChar):TADOConnection;stdcall;
begin
result:=GetConnectionFromPool(aDBName); if result=nil then
begin
result:=RequestConnectionByRPC(aDBName);
end; if result=nil then ShowMessage('No database connection be created.');
end;{-Biz logic===================================================================-}
{-Mem Map=====================================================================-}
procedure CloseMemMap;
begin
if pConnPool <> nil then
UnMapViewOfFile(pConnPool);
if hMapping <> 0 then
CloseHandle(hMapping);
end;function LockMemMap: Boolean;
begin
Result := true;
hMapMutex := CreateMutex(nil, false, NAME_MUTEX);
if hMapMutex = 0 then
begin
ShowMessage('Failed to create a Map Mutex.');
Result := false;
end else
begin
if WaitForSingleObject(hMapMutex, REQUEST_TIMEOUT) = WAIT_FAILED then
begin
ShowMessage('The Map Mutex can NOT be locked.');
Result := false;
end;
end;
end;procedure UnlockMemMap;
begin
ReleaseMutex(hMapMutex);
CloseHandle(hMapMutex);
end;function OpenMemMap:boolean;
begin
result:=false;
hMapping:=OpenFileMapping(FILE_MAP_WRITE,false,NAME_MEM_MAP);
if hMapping=0 then
begin
hMapping := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0,
SizeOf(TConnectionPool), NAME_MEM_MAP);
if (hMapping = 0) then
begin
ShowMessage('Failed to create map file.');
exit;
end;
end; pConnPool := PConnectionPool(MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0));
if pConnPool = nil then
begin
CloseHandle(hMapping);
ShowMessage('The Memory Map can NOT be viewed.');
exit;
end; result:=true;
end;
{-Mem Map=====================================================================-}
exports
CreateAConnection, AllocateConnection;initialization
OpenMemMap;
LockMemMap;finalization
CloseMemMap;
UnlockMemMap;end.
解决方案 »
- 请问如何实现将bmp转换为四色显示?
- 紧急求助!!我建立了一个treeview,可是当我点击树上面的项目的时候总是报错!是找不到我选中的那个选项的selectedindex.怎么办?
- 求助:三层中如何实现数据上传下载
- 关于添加treeview节点对象问题
- 怎样使用delphi7中的Indv的IdUDPClient和IdUDPServer控件,在线等
- 怎么取得用户两次按键之间的间隔,并用此来推算用户的输入速度?
- 逻辑型变量的定义方法?
- 怎样将数字的年月日转换成文字的年月日?????
- 有个想法,大家进来讨论讨论吧
- 如何判断TTreeView中的节点是否是继承关系?
- Communication link failure
- 调用窗口的数值回传问题
另外你说“其他两字段的值正常”,我咋就不信 FDBNameSet 这种指针能正常呢
To Seamour:
我说的其他两个字段是指下面这个记录类型的FDBNameSet和FConnectionCount的值是能成功的共享的,可能是因为系统基本类型,复制的时候不是只复制指针,貌似对象的话只复制指针引用,我非常同意你的说法,但是我不知道应该如何改。还请赐教。大学时看到指针就头痛。(:-TConnectionPool=record
FDBNameSet:array[0..COUNT_MAX_CONNECTION] of PChar;
FDBConnSet:array[0..COUNT_MAX_CONNECTION] of TADOConnection;
FConnectionCount:Integer;
end; To mdejtod:
pConnPool应该是在创建映射的时候系统自动分配的.
但对象指针就没这么幸运了,所以表面上看,你的 FDBNameSet 指针“成功的共享”了,而 FDBConnSet 却没有,这两个的道理是一样的。你要是不信的话,等以后“恰好”没“成功的共享”的时候就慢慢调去吧。另,在不同的模块或进程间试图“共享” delphi 对象是个很糟糕的想法,劝你还是放弃吧