2014-09-23 122 views
2

我有一个正在运行的线程应用程序正在计算一些更长的计算。通过AnonymousThread传递值onTerminate

procedure TForm.calculationInThread(value: Integer); 
var aThread : TThread; 
begin 
    aThread := 
    TThread.CreateAnonymousThread(
     procedure 
     begin 
     myCalculation(value);   
     end 
    ); 
    aThread.FreeOnTerminate := True; 
    aThread.OnTerminate := self.calculationInThreadEnd; 
    aThread.Start; 
end; 

并且执行calculateInThreadEnd;

procedure TForm.calculationInThreadEnd(Sender: TObject); 
begin 
    doSomething; 
end; 

我可能会错过一些愚蠢的事情,但如何将一个值传递给calculateInThreadEnd?我发现

TThread.SetReturnValue(value); 

但我如何访问onTerminate调用?

type THackThread = class(TThread); 

procedure TForm1.calculationInThreadEnd(Sender: TObject); 
var Value: Integer; 
begin 
    Value := THackThread(Sender as TThread).ReturnValue; 
end; 

回答

4

OnTerminate事件的Sender参数是线程对象。所以,你可以这样做:

aThread := 
    TThread.CreateAnonymousThread(
    procedure 
    begin 
     myCalculation(value);   
     TThread.SetReturnValue(...); 
    end 
); 

然后在OnTerminate事件处理程序,你可以这样做:

procedure TForm.calculationInThreadEnd(Sender: TObject); 
var 
    Value: Integer; 
begin 
    Value := (Sender as TThread).ReturnValue; 
end; 

更新

返回值财产受到保护,所以你需要使用受保护的黑客可以访问它。

+0

我不能访问它这样的,它失败,出现错误 [dcc32错误] Unit1.pas(33):E2362无法访问受保护的符号TThread.ReturnValue 和TThread类不包含名为“返回值” – Zibelas 2014-10-15 11:19:24

+0

成员然后使用受保护的黑客。然而,所有这些挣扎表明,这整个方法不是最好的方法。 – 2014-10-15 11:36:18

+0

CreateAnonymousThread正在返回TThread,所以即使我尝试使用proteceted hack,它也会编译但与无效的类型转换崩溃。我喜欢AnonymousThread的简单性,我不需要在启动时访问正在运行的线程,我只想知道哪个线程在调用calculateInThreadEnd时结束。 OFc我可以做一个列表(fifo或类似的东西),在那里添加线程标识符并在calculateInThreadEnd函数中处理它。但我认为会有更优雅和干净的解决方案。 – Zibelas 2014-10-15 14:37:37