DELPHI:多线程客户端/服务器datasnap错误
这是我在这里的第一篇文章 - 所以要温柔:-)
我想构建一个使用datasnap进行数据传输的客户端/服务器应用程序。
这是一项相当简单的任务 - 有很多例子需要学习。
但是 - 拥有一个Datasnap服务器(从Delphi XE向导构建)我发现自己遇到了问题,我希望有人可以引导我走向正确的方向。
服务器和客户端在同一台PC上运行(这就是现在的设计)。
服务器正在运行会话生命周期。
服务器和客户共享一个类(在下面发布)..
Server提供了一个简单的方法 - 使用GetNewObject方法的GetServerObject。
服务器本身是一个VCL应用程序 - 主要形式是fmServer。
OnCreate实例化Servers FormObject属性(FormObject:= TMyDataObject.Create);
function TServerMethods2.GetNewObject: TMyDataObject;
begin
Result := TMyDataObject.Create;
end;
function TServerMethods2.GetServerObject: TMyDataObject;
begin
Result := GetNewObject;
if not Result.Assign(fmServer.FormObject) then
raise Exception.Create('Server error : Assign failed!');
end;
所有这一切都是微不足道的 - 只有当我将我的客户端应用程序转换为多线程怪物时才会出现我的问题:-)(读取 - 超过1个线程)。
所以这是客户端的线程代码。
TDataThread = class(TThread)
private
DSConn: TSQLConnection;
protected
procedure Execute; override;
public
constructor Create(aConn: TSQLConnection); overload;
end;
constructor TDataThread.Create(aConn: TSQLConnection);
begin
inherited Create(False);
DSConn := aConn.CloneConnection;
FreeOnTerminate := true;
end;
procedure TDataThread.Execute;
var
DSMethod: TServerMethods2Client;
aDataObject : TMyDataObject;
begin
NameThreadForDebugging('Data');
{ Place thread code here }
DSMethod := nil;
try
while not terminated do
begin
sleep(10);
if DSConn.Connected then
begin
try
if DSMethod = nil then
DSMethod := TServerMethods2Client.Create(DSConn.DBXConnection,false);
if DSMethod <> nil then
try
aDataObject := DSMethod.GetserverObject;
finally
freeandnil(aDataObject);
end;
except
freeandnil(DSMethod);
DSConn.Connected := False;
end
end
else
begin
// connect
try
sleep(100);
DSConn.Open;
except
;
end;
end;
end;
finally
freeandnil(DSMethod);
DSConn.Close;
freeandnil(DSConn);
end;
当我创建多个这些线程时 - 最终我会得到一个错误(“无法实现...”或某些“远程dbx错误......”等等。
我根本无法让它工作 - 所以我可以产生数百个线程/连接到datasnap服务器。
我知道这个问题很棘手 - 但我希望有人比我更聪明:-)
如果我尝试相同的客户端线程代码 - 但访问一个更简单的服务器方法(让我们说样本中的echostring),那么我可以运行数百个线程。
也许我在这里回答自己 - 但我太盲目无法实现它:-)
unit uDataObject;
interface
uses
SysUtils;
Type
TMyDataObject = class(TObject)
private
fString: String;
fInteger: Integer;
public
constructor Create; virtual;
destructor Destroy; override;
function Assign(aSource: TMyDataObject): boolean;
property aString: String read fString write fString;
property aInteger: Integer read fInteger write fInteger;
end;
implementation
{ TMyDataObject }
function TMyDataObject.Assign(aSource: TMyDataObject): boolean;
begin
if aSource <> nil then
begin
try
fString := aSource.aString;
fInteger := aSource.aInteger;
Result := True;
except
Result := false;
end;
end
else
Result := false;
end;
constructor TMyDataObject.Create;
begin
inherited;
Randomize;
fString := 'The time of creation is : ' + FormatDateTime('ddmmyyyy hh:nn:ss:zzz', Now);
fInteger := Random(100);
end;
destructor TMyDataObject.Destroy;
begin
inherited;
end;
end.
所有帮助表示赞赏
没有找到相关结果
已邀请:
2 个回复
凰葱崎济邯
替秀宝