これは私の最初の投稿です - だから優しくしてください :-)
データ転送に datasnap を使用するクライアント/サーバー アプリケーションを構築したいと考えています。これはかなり単純な作業です。多くの例から学ぶことができます。しかし - Datasnap サーバー (Delphi XE ウィザードからビルド) を持っていると、問題が発生します。誰かが私を正しい方向に導いてくれることを願っています。
サーバーとクライアントは同じ PC で実行されます (これが現在の設計です)。サーバーはセッション ライフサイクルを実行しています。サーバーとクライアントはクラスを共有します (以下に掲載)。
サーバーは、GetNewObject メソッドを使用する単純なメソッド GetServerObject を提供します。サーバー自体は 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;
これはすべて非常に些細なことです-そして、私の問題は、クライアントアプリケーションをマルチスレッドモンスターにひねった場合にのみ発生します:-) (読み取り-複数のスレッド)。
クライアントのスレッド コードは次のとおりです。
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.
すべての助けに感謝します