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;