2011-09-16 12 views
2

我正在使用TIdHTTPServer創建一個簡單的Indy網絡服務器。幾乎所有請求服務器需要與數據庫通信(通過TAdoConnection)。鑑於資源方面的數據庫連接有點昂貴,我想創建一個池化機制來重用連接;而不是在每個請求上建立連接。IdHTTPserver:Share ADOConnection

我已經搜索失敗的例子。 This Link關於Embarcadero討論論壇建議子分類後裔TIdSchedulerOfThreadPoolTIdThreadWithTask。但我仍然無法把它們放在一起。

我是否需要重寫TIdSchedulerOfThreadPool.NewThread方法,並使其返回我的子類TIdThreadWithTask對象這反過來將有自己的TAdoConnection對象?

有沒有人有一個例子?我是不是應該爲此擔心,只是在每個請求上打開數據庫連接?

回答

3

你爲什麼不自己管理泳池?

你有一個連接列表。它開始是空的。每次請求到來時,都會查找可用的連接(活動但未被使用的連接)。如果找不到,則創建一個並將其放入列表中,因爲不可用。請求結束後,您將連接設置爲可用。

在那裏,做到了,不要後悔做!令人關注的幾個要點:記住

  • 保持線程安全任何時候都:
    • 當查詢列表
    • 當你當你設置連接的可用性查詢連接的可用性
  • 有時候,請檢查您是否有太多未使用的連接可用,可能會超出您的需要,因此必須將它們設置爲不可用,從列表中刪除,然後關閉d。
+0

這聽起來很容易。因此,創建一個類TMyConnectionObject,它將具有TAdoConnection對象和一個布爾型「Active」。我有一個GLOBAL TStringList或TList來存儲它們。當OnCommandGet被觸發時,我遍歷所有的對象以找到一個「InActive」。如果有一個我使用它;否則創建並添加。 OnCommandGet是否有可能在同一時間被觸發,並且我的處理會提取與可用對象相同的對象? –

+0

爲了保持線程安全,我是否只使用Critical部分? –

+0

你明白了。閱讀我的更新:有兩個連接線程嘗試同時訪問列表的機會。您必須使用特定於線程的策略:線程安全列表(http://docwiki.embarcadero.com/CodeExamples/en/TThreadList_(Delphi)),CriticalSection等。您可能還想閱讀以下內容:http:// www。 eonclash.com/Tutorials/Multithreading/MartinHarvey1.1/ToC.html –

3

你還必須確保COM設置正確的每個線程與到對呼叫: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

肯定的一件事......不要「掛起」具有開放式數據庫連接的線程。正如我之前評論的那樣,我會讓微軟管理ADO連接池,因爲他們已經做得很好。我會在每個Context上創建/釋放一個ADOConnection - 它將默認由微軟合併。 –

相關問題