gpt4 book ai didi

multithreading - DELPHI:多线程客户端/服务器数据快照错误

转载 作者:行者123 更新时间:2023-12-03 15:36:44 26 4
gpt4 key购买 nike

这是我在这里发表的第一篇文章 - 所以要温柔:-)

我想构建一个使用 datasnap 进行数据传输的客户端/服务器应用程序。这是一项相当简单的任务 - 并且有很多示例可供学习。但是 - 拥有 Datasnap 服务器(从 Delphi XE 向导构建)时,我发现自己遇到了问题,我希望有人可以引导我走向正确的方向。

服务器和客户端运行在同一台PC上(这是目前的设计)。服务器正在运行Session生命周期。服务器和客户端共享一个类(下面发布)..

服务器提供了一个简单的方法 - GetServerObject,它使用 GetNewObject 方法。服务器本身是一个VCL应用程序——主要形式是fmServer。OnCreate 实例化服务器 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;

当我创建超过 1 个这样的线程时 - 最终我会收到一个错误(“无法实例化...”或一些“远程 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.

感谢所有帮助

最佳答案

这大部分已在评论和错误报告中得到解答,但是...您看到的问题是由 XE 编码器代码中的多线程问题引起的。如果两个线程(或两个客户端)同时调用接受或返回用户定义类型(任何将使用编码器/解码器的类型)的服务器服务器方法,则可能会发生异常。

我不知道 XE 的完美解决方法,但如果可以不使用用户定义的类型,那么您不应该看到多线程问题。

垫子

关于multithreading - DELPHI:多线程客户端/服务器数据快照错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5580234/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com