2013-10-04 115 views
7

我讀答案another question here大約需要CoInitialize的運行和couninitialize初始化和清理連接到ADO對象。我需要做一些類似的事情來在一個線程中執行soap調用。螺紋在delphi

有沒有一種方法可以覆蓋一個TThread對象,讓之前和之後的線程自動運行

對於這個例子,我們轉換到一個SOAP後端,並且需要做大量的工作,它會節省一些時間來重寫一個新的SOAP友好型TThread,而不是爲每個線程添加coinitialize和couninitialze。但在一般情況下,初始化清理線程內螺紋有時似乎是一個不錯的主意。現在看來你只能做一個或另一個。

+0

換句話說,是的。彼得,你這樣做的擔心是什麼? –

回答

7

也許你想是這樣的:

type 
    TMyThread = class sealed(TThread) 
    private 
    FOnBeforeExecute: TProc; 
    FOnExecute: TProc; 
    FOnAfterExecute: TProc; 
    protected 
    procedure Execute; override; 
    public 
    property OnBeforeExecute: TProc read FOnBeforeExecute write FOnBeforeExecute; 
    property OnExecute: TProc read FOnExecute write FOnExecute; 
    property OnAfterExecute: TProc read FOnAfterExecute write FOnAfterExecute; 
    end; 

procedure TMyThread.Execute; 
begin 
    if Assigned(OnBeforeExecute) then 
    OnBeforeExecute; 
    try 
    if Assigned(OnExecute) then 
     OnExecute; 
    finally 
    if Assigned(OnAfterExecute) then 
     OnAfterExecute; 
    end; 
end; 

我做了一個密封類,讓你不能的東西,打破了設計取代Execute。額外的好處是你可以使用事件將線程過程從實現類中分離出來。

+0

這很酷,解耦方法是像大多數我們的線程的工作已經,但是這是相當多的優雅。非常感謝你! –

+0

爲什麼在這個世界上你需要事件呢?只是要像'ExecuteContext'從'CoInitialize的,CoUninitialize'對中稱爲虛擬方法並覆蓋'ExecuteContext'在你的後裔。我根本不喜歡這個。 – TLama

+0

'TMyBaseThread'和'sealed'在一行中對我來說聽起來很奇怪......也許改名字? – jpfollenius

5

如果要採取具體的初始化和結束與大衛的回答像事件做護理意味着你必須分配爲您創建的每個線程的事件。這意味着要麼添加一個特定的構造函數來傳遞它們,要麼創建處於掛起模式的線程。

個人而言,我真的不喜歡不必記得做所有這些事情,因此會去一個更多態性的解決方案:

type 
    TInitializeFinalizeThread = class(TThread) 
    protected 
    procedure InitializeExecution; virtual; 
    procedure FinalizeExecution; virtual; 
    procedure InternalExecute; virtual; 
    procedure Execute; override; 
    end; 

procedure TInitializeFinalizeThread.Execute; 
begin 
    InitializeExecution; 
    try 
    InternalExecute; 
    finally 
    FinalizeExecution; 
    end; 
end; 

需要做奧萊東西線程可能再有一個共同的基礎,需要護理初始化和finialization的:

type 
    TOleThread = class(TInitializeFinalizeThread) 
    protected 
    procedure InitializeExecution; override; 
    procedure FinalizeExecution; override; 
    end; 

procedure TOleThread.InitializeExecution; 
begin 
    CoInitialize; 
end; 

procedure TOleThread.FinalizeExecution; 
begin 
    CoUninitialize; 
end; 

這意味着,實際上要做些什麼類可以剛剛從TOleThread繼承和放心,初始化和結束已經照顧,所以他們只需要覆蓋InternalExecute

type 
    TWordMailMergeThread = class(TInitializeFinalizeThread) 
    protected 
    procedure InternalExecute; override; 
    end; 

procedure TWordMailMergeThread.InternalExecute; 
begin 
    // Whatever you need this to do. 
end; 

雖然他們當然可以自由重寫InitializeExecutionFinalizeExecution方法來設置,並退出至OleServer連接(字在這個例子中),而不是在InternalExecute做的。

+0

InternalExecute是否應該聲明爲抽象的,以便編譯器指示需要實現什麼? –

+0

@ J.岡薩雷斯:是的,不必但是,它可以幫助。多少取決於你繼承的繼承樹(深度)。請記住,雖然IIRC編譯器只能捕獲顯式類型實例。如果你通過元類實例化一個類('TOleThreadClass = TOleThread類'),你將不會得到編譯器的幫助,但會得到運行時異常。 –