你還必須確保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;
這聽起來很容易。因此,創建一個類TMyConnectionObject,它將具有TAdoConnection對象和一個布爾型「Active」。我有一個GLOBAL TStringList或TList來存儲它們。當OnCommandGet被觸發時,我遍歷所有的對象以找到一個「InActive」。如果有一個我使用它;否則創建並添加。 OnCommandGet是否有可能在同一時間被觸發,並且我的處理會提取與可用對象相同的對象? –
爲了保持線程安全,我是否只使用Critical部分? –
你明白了。閱讀我的更新:有兩個連接線程嘗試同時訪問列表的機會。您必須使用特定於線程的策略:線程安全列表(http://docwiki.embarcadero.com/CodeExamples/en/TThreadList_(Delphi)),CriticalSection等。您可能還想閱讀以下內容:http:// www。 eonclash.com/Tutorials/Multithreading/MartinHarvey1.1/ToC.html –