2011-09-16 6 views
2

私は、TIdHTTPServerを使用して簡単なIndy Webサーバーを作成しています。ほぼすべての要求で、サーバーはデータベースと通信する必要があります(TAdoConnection経由)。データベース接続がリソースの面でやや高価であることを見て、私は接続を再利用するためのプーリングメカニズムを作成したいと思います。要求ごとに接続するのではなく、IdHTTPserver:ADOConnectionを共有する

例の検索に失敗しました。 EmbarcaderoディスカッションフォーラムのThis Linkは、サブクラスの子孫を、TIdSchedulerOfThreadPoolををTIdThreadWithTaskとすることを提案しています。しかし、私はまだそれをすべて一緒にすることはできません。

は私がTIdSchedulerOfThreadPool.NewThreadメソッドをオーバーライドして、それが順番にそれが自分のTADOConnectionのオブジェクトのだろう、私のサブ分類TIdThreadWithTaskオブジェクトを返す持っている必要がありますか?

例がありますか?私はこれについて心配する必要はなく、各リクエストでデータベース接続を開くだけですか?

答えて

3

あなたは自分でプールを管理してみませんか?

接続の一覧があります。それは空になる。リクエストが来るたびに、利用可能な接続(アクティブであるが使用されていない接続)を探します。何も見つからなければ、それを作成し、それを利用不可能としてリストに入れます。要求が終了すると、接続を使用可能に設定します。

そこに行って、それをやって、後悔しないでください!懸念のいくつかのポイント:

  • 心の中ですべての回をスレッドセーフにしてください:
    • あなたは、接続の可用性
    を設定するときは、接続の可用性
  • を照会するときは、リスト
  • を照会する場合
  • 時々、未使用の接続が多すぎるかどうかを確認します。必要以上のものがある可能性があるため、使用不可に設定してリストから削除してから閉じる必要がありますd。あなたはまた、COMがペアを呼び出して、各スレッドに正しくセットアップされていることを確認する必要が
+0

本当に簡単ですね。ですからTAdoConnectionオブジェクトとブール値「アクティブ」を持つクラスTMyConnectionObjectを作成してください。そして私はGLOBAL TStringListまたはTListを持っています。 OnCommandGetが起動されると、私はすべてのオブジェクトをループして、「非アクティブ」を探します。もし私がそれを使用していれば;それ以外の場合は作成して追加します。 OnCommandGetが正確に同じタイミングで起動され、処理が同じオブジェクトを取得する可能性はありますか? –

+0

スレッドの安全性を念頭に置くには、クリティカルセクションを使用するだけですか? –

+0

あなたはポイントを持っています。私の更新を読む:2つの接続スレッドが同時にリストにアクセスしようとする可能性があります。スレッドセーフなリスト(http://docwiki.embarcadero.com/CodeExamples/en/TThreadList_(Delphi))、CriticalSectionなど、スレッド固有の戦略を使用する必要があります。http:// www。 eonclash.com/Tutorials/Multithreading/MartinHarvey1.1/ToC.html –

3

:CoInitializeを/に、counitialize

以下は、プロジェクトに含める例のユニットです。そしてあなたのHTTPサーバーコンストラクタでは、カスタムスケジューラを作成するだけで、Indyはデフォルトの代わりにこれを使用します。

これを行うと、各クライアントスレッドはCOM用に適切に初期化され、すべてのクライアントスレッドで共有される他のアイテムを追加することもできます。

また、接続ごとにカスタムのTIdServerContext子孫を作成します(HTTPサーバーコンストラクタでもContextClassプロパティを設定します)。異なる種類のサーバーには異なるTIdServerContext子孫がありますが、すべてTsoIndyCOMEnabledSchedulerOfThreadベーススレッドクラスをすべて使用します何らかのCOMをする。

スレッドにADO接続を挿入するのではなく、コンテキストに挿入します。特にこれをスレッドプールに追加する場合は特にです。

unit ExampleStackOverflow; 

interface 

uses 
    SysUtils, Classes, 
    ActiveX, 
    IdThread, IdSchedulerOfThreadDefault; 

type 
    //Meant to be used with a custom TIdSchedulerOfThreadDefault descendant 
    //to ensure COM support on child threads. 
    TsoIndyComThreadWithTask = class(TIdThreadWithTask) 
    protected 
    //Ensure COM is setup before client connection/thread work 
    procedure BeforeExecute; override; 
    //Graceful COM cleanup on client connection/thread 
    procedure AfterExecute; override; 
    end; 


    TsoIndyCOMEnabledSchedulerOfThread = class(TIdSchedulerOfThreadDefault) 
    public 
    constructor Create(AOwner:TComponent); reintroduce; 
    end; 



implementation 

procedure TsoIndyComThreadWithTask.BeforeExecute; 
begin 
    CoInitialize(nil); 
    inherited; 
end; 


procedure TsoIndyComThreadWithTask.AfterExecute; 
begin 
    inherited; 
    CoUninitialize(); 
end; 


constructor TsoIndyCOMEnabledSchedulerOfThread.Create(AOwner:TComponent); 
begin 
    inherited; 
    //the whole reason for overriding default scheduler of thread is to setup COM 
    //on client threads 
    ThreadClass := TsoIndyComThreadWithTask; 
    Name := Name + 'COMEnabledScheduler'; 
end; 
+0

詳細な回答ありがとうございます。私はそれを消化しようとする必要があります。これは私が上手く対処していないものです。 –

+0

確かに...オープンされたデータベース接続を持つスレッドを "中断"しないでください。私が前にコメントしたように、私はMicrosoftが既にADO接続プールを管理しているので、彼らはそれをうまくやっています。私は各コンテキストでADOConnectionを作成/解放します。デフォルトではMicrosoftによってプールされます。 –

関連する問題