2013-10-04 82 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类'),你将不会得到编译器的帮助,但会得到运行时异常。 –