0

私は2つのプログラムを持っています。1つはクライアントで、もう1つはクライアント用のサーバーです。クライアントは次のようにサーバーにデータを送信し、応答を読み取ります。

 idtcpclient1.WriteLn(command); //Command contains data that the server needs eg. name and surname
 progressbar1.StepIt;
 sresult := idtcpclient1.ReadLn();

次に、サーバーは行を読み取り、操作して、SQL クエリを作成します。

adoquery1.Close;
adoquery1.SQL.Text := 'select * from '+sGrade;
adoquery1.Open;

しかし、データベースへの接続を開くとすぐに、クライアントは「接続が正常に閉じられました」というエラーを出します

入力をシミュレートすることにより、クライアントなしでサーバーコードをテストしましたが、正常に動作します。

Indy と AdoQuery が競合していると思います。競合している場合、なぜ、どのように修正できますか

そうでない場合、何が問題で、どうすれば修正できますか?

4

2 に答える 2

2

ADO は、アパートメント スレッドの COM オブジェクトを使用します。これらの COM オブジェクトは、それらを作成するスレッドと親和性があります。マーシャリングされていない限り、スレッド境界を越えて使用することはできません。

Indy の TCP サーバーはマルチスレッドです。各クライアントは独自のスレッドで実行されます。

スレッドはCoInitialize/Ex()、COM オブジェクトにアクセスする前に、COM との関係を確立するために呼び出し、CoUninitialize()COM を使用して終了したときに呼び出す必要があります。

クライアントを切断するキャッチされない例外が発生しているため、サーバーは失敗します。COM を初期化していない可能性があります。

クライアントごとに ADO オブジェクトを作成する必要があります。メイン スレッドから使​​用しないでください。サーバーのOnConnectイベントで、 を呼び出しますCoInitialize/Ex()OnDisconnectイベントでは、 を呼び出しますCoUninitialize()。イベントではOnExecute、必要に応じて新しい ADO オブジェクトを動的に作成して使用します。

これは、各クライアントが独自のデータベース接続を必要とすることを意味します。それが望ましくない場合は、ADO ロジックを、必要に応じてクライアントが要求を送信できる専用スレッドに移動します。メインスレッドでデータベースの作業を行うことは避けてください。メインスレッドには属していません。

于 2014-06-19T15:29:47.513 に答える
0

データモジュールを使用する場合: スレッド化エラーを回避するために、クライアントごとにデータモジュールのインスタンスを 1 つ作成できます。Indy は、コンテキスト内のクライアントのデータモジュールへの参照を保持できます。または、利用可能なリソースとトラフィックに応じて、データモジュール インスタンスのプールを使用します。

于 2014-06-19T14:54:22.027 に答える