线程产生的功能结果总是延迟吗?

时间:2019-04-13 05:45:36

标签: multithreading function delphi

我想从线程中得到一个整数结果。这只是一个简单的计算。 我的问题是,我无法从中获得“即时”结果。我执行了不止一次,然后得到了正确的结果。

这里是单位形式:

unit Unit1;

interface

uses
  System.SysUtils,
  System.Classes,
  Vcl.Controls, Vcl.Forms, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    btn1: TButton;
    mmo1: TMemo;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure CaclDone(Sender: TObject);
    procedure BeginCal(calA, calB: Integer);
    function StartCalc(const calA, calB: Integer): Int64;
  end;

var
  nOut: Int64;
  Form1: TForm1;

implementation

{$R *.dfm}

uses uCalculationThread;

procedure TForm1.BeginCal(calA: Integer; calB: Integer);
var
  P: TCalc;
begin
  nOut := 0;
  P := TCalc.Create;
  P.numa := calA;
  P.numb := calB;
  P.OnTerminate := CaclDone;
  P.Start;
end;

procedure TForm1.CaclDone(Sender: TObject);
var
  P: TCalc;
begin
  P := TCalc(Sender);
  nOut := P.iOut;
  mmo1.Lines.Add('on thread finished : ' + IntToStr(nOut)); // < here is instant result
end;

function TForm1.StartCalc(const calA, calB: Integer): Int64;
begin
  BeginCal(calA, calB);
  Result := nOut;
end;

procedure TForm1.btn1Click(Sender: TObject);
var
  i: Int64;
begin
  i := StartCalc(10, 20);
  mmo1.Lines.Add('on function call : ' + IntToStr(i)); // first result always 0
end;

end.

这是穿线单元

unit uCalculationThread;

interface

uses
  System.Classes;

type
  TCalc = class(TThread)
  private
    fiOut: Int64;
    fnumA, fNumB: Integer;
  protected
    procedure Execute; override;
  public
    property numA: Integer read fnumA write fnumA;
    property numb: Integer read fNumB write fNumB;
    property iOut: Int64 read fiOut write fiOut;
    constructor Create;
  end;

implementation

constructor TCalc.Create;
begin
  inherited Create(True);
  FreeOnTerminate := True;
end;

procedure TCalc.Execute;
begin
  fiOut := fnumA + fNumB;
end;

end.

我需要一个简单的函数来获取该线程的结果。

1 个答案:

答案 0 :(得分:4)

考虑此方法:

function TForm1.StartCalc(const calA, calB: Integer): Int64;
begin
  BeginCal(calA, calB);
  Result := nOut;
end;

它调用BeginCal,它创建一个线程并开始执行。线程的结果通过OnTerminate事件传递,该事件调用CaclDone并将结果分配给nOut变量。

由于OnTerminate事件是在主线程中执行的,因此将在执行StartCalc后发生。因此,StartCalc将没有有效的值可以返回。


  

我需要一个简单的函数来获取该线程的结果。

这意味着主线程将不得不等待线程完成其执行。这破坏了GUI的行为方式。

您已经拥有一种通过CaclDone方法获取结果的机制。


在这种情况下,处理异步计算链的方法是执行以下操作(使用System.Threading):

function MyAdd( a,b : Int64): Int64;
begin
  Result := a + b;
end;

procedure TForm1.btn1Click(Sender: TObject);
begin
  TTask.Create(
    procedure
    var
      i: Int64;
    begin
      i := MyAdd(10,20);
      TThread.Queue(nil,  // Result is presented in the main thread.
        procedure
        begin
           mmo1.Lines.Add('on function call : ' + IntToStr(i));
           if (i <> 4) then
             mmo1.Lines.Add('on function call : <> 4'); 
        end);
    end).Start;
end;