4

これは私の最初の投稿です - だから優しくしてください :-)

データ転送に 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.

すべての助けに感謝します

4

2 に答える 2

0

これはほとんどコメントとバグ レポートで回答されていますが、... 表示されている問題は、XE のマーシャラー コードのマルチスレッドの問題が原因です。2 つのスレッド (または 2 つのクライアント) が、ユーザー定義型 (マーシャラー/アンマーシャラーを使用する任意の型) を受け取るか返すサーバー サーバー メソッドを同時に呼び出すと、例外が発生する可能性があります。

XE の完全な回避策はわかりませんが、ユーザー定義型を使用しないことが可能であれば、マルチスレッドの問題は発生しません。

マット

于 2011-05-03T14:46:10.903 に答える
0

単純なサーバー メソッドが機能している場合、「実際の」コードが実行または使用している何かで問題を発見する必要があると思います。

それは接続にある可能性があります(接続を使用するように単純なコードを変更してみてください)あなたの問題はCloneConnectionにもある可能性があります。複製元の接続が解放されると、複製された接続が解放されます。http://docwiki.embarcadero.com/VCL/en/SqlExpr.TSQLConnection.CloneConnectionを参照してください 。

于 2011-04-08T07:56:05.563 に答える