Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 线程始终延迟导致的函数结果?_Multithreading_Function_Delphi - Fatal编程技术网

Multithreading 线程始终延迟导致的函数结果?

Multithreading 线程始终延迟导致的函数结果?,multithreading,function,delphi,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;

我想从一个线程生成一个整数结果。这只是一个简单的计算。 我的问题,我不能有一个“即时”的结果。我执行了多次,然后得到了正确的结果

以下是单位形式:

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.
我需要的是一个简单的函数,从该线程获得结果。

考虑以下方法:

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):

函数MyAdd(a,b:Int64):Int64;
开始
结果:=a+b;
结束;
程序TForm1.btn1Click(发送方:TObject);
开始
任务,创建(
程序
变量
i:Int64;
开始
i:=MyAdd(10,20);
队列(nil,//结果显示在主线程中。
程序
开始
mmo1.Lines.Add('on函数调用:'+IntToStr(i));
如果(i)4那么
mmo1.Lines.Add('on function call:4');
(完),;
结束)开始;
结束;

直到线程完成,才知道结果。使用OnTerminate是正确的方法。您还可以等待线程完成。但这会使线程变得毫无意义。当我读到你的问题时,听起来这就是你想要做的。在这种情况下,只需移除螺纹。如果您有计算管道(即计算2取决于计算1的结果),则最好使用。我怀疑您对螺纹的理解不足。您不使用线程来获得“即时”结果。线程只是允许多段代码同时(并行)执行的一种手段。代码在线程中的运行速度不会更快。这当然不是即时的。事实上,由于启动一个新线程的开销,它的速度较慢。好处是能够在代码运行时执行其他操作。例如,像泵送一个消息队列来保持您的UI响应。我的强烈建议是阅读更多关于线程和并行计算的介绍性文章。我真诚地建议您再次阅读我的评论,并注意其中给出的建议。如果这是一个需要立即得到结果的计算,那么它不属于线程,无论它是否是一个繁重的计算。线程被设计为在后台运行,以便在不干扰UI或其他处理的情况下执行操作。如果它不能在后台运行,因为您现在需要结果,那么就不要在线程中运行它,如果您需要它在线程中运行以保持UI响应,那么就不要以立即需要结果的方式编写代码。
function TForm1.StartCalc(const calA, calB: Integer): Int64;
begin
  BeginCal(calA, calB);
  Result := nOut;
end;
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;