gpt4 book ai didi

delphi 变量值在循环中的线程中发生变化

转载 作者:行者123 更新时间:2023-12-03 15:47:31 26 4
gpt4 key购买 nike

我的代码正在运行一个 for 循环来处理一些数据,如下所示

procedure printValue(Value: Integer);
begin
TThread.Synchronize(TThread.Current, procedure
begin
form1.memo1.lines.add( Value.ToString );
end);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
myThread : TThread;
Proc1: TMyProc;
begin
for I := 0 to 10 do
begin
myThread := TThread.CreateAnonymousThread(
procedure
begin
printValue( i );
end);
myThread.Start;
end;
end;

这段代码的输出是这样的:

3
5
6
8
9
11
10
4
11
4
7

这不好,所以我添加了一个小的延迟,例如 sleep(1)线程启动后。这将解决输出问题,但不是一个好主意,因为在大循环中会阻塞 ui 线程,因此尝试使用 this document as help所以我的代码改变如下:

function CaptureValue(Value: Integer): TMyProc;
begin
Result := procedure begin Writeln(Value); end;
end;

procedure printValue(Value: Integer);
begin
TThread.Synchronize(TThread.Current, procedure
begin
form1.memo1.lines.add( Value.ToString );
end);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
myThread : TThread;
Proc1: TMyProc;
begin
for I := 0 to 10 do
begin

myThread := TThread.CreateAnonymousThread(
procedure
begin
Proc1:= CaptureValue(i);
printValue( Proc1 );
end);
myThread.Start;
end;
end;

但是我得到了[dcc32 Error] Unit11.pas(57): E2010 Incompatible types: 'Integer' and 'procedure, untyped pointer or untyped parameter'错误。

我的代码有什么问题吗?

最佳答案

匿名过程捕获变量,而不是值。 This is documented behavior 。因此,在您的两个示例中,您的线程共享单个 I变量的访问没有同步。

你的想法是正确的,通过 I到一个过程,然后在使用它之前从参数列表中捕获它。然而,你的做法是错误的。

您的第二个示例实际上无法编译的原因是您滥用 CaptureValue() 。它返回 TMyProc ,这显然是 reference to procedure (顺便说一句,RTL 已经有一个 TProc 用于相同目的)。您正在将匿名过程按原样传递给 printValue() ,需要 Integer反而。这就是编译器错误所提示的。

您使用返回值的方式,CaptureValue()必须返回一个匿名函数,该函数本身返回 Integer (即,让 CaptureValue() 返回 reference to function: Integer ,又名 TFunc<Integer> ),然后调用该函数并将返回值传递给 PrintValue() .

您仍在捕获I在将其传递给 CaptureValue() 之前不过,所以您仍然有线程共享 I 。您需要调用CaptureValue()在调用 CreateAnonymousThread() 之前直接在循环内部。但是,您的线程将捕获并共享 Proc1相反,你会回到原来的问题。

话虽如此,尝试更像这样的事情:

procedure PrintValue(Value: Integer);
begin
TThread.Synchronize(nil,
procedure
begin
Form1.Memo1.Lines.Add( Value.ToString );
end
);
end;

function CaptureAndPrintValue(Value: Integer): TProc;
begin
Result := procedure
begin
printValue( Value );
end
);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
begin
for I := 0 to 10 do
begin
TThread.CreateAnonymousThread(
CaptureAndPrintValue(I)
).Start;
end;
end;

或者,您可以让 RTL 为您处理线程:

uses
..., System.Threading;

procedure PrintValue(Value: Integer);
begin
// can't use TThread.Synchronize() with TParallel, as it
// doesn't service the main message queue while looping...
TThread.Queue(nil,
procedure
begin
Form1.Memo1.Lines.Add( Value.ToString );
end
);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
TParallel.For(0, 10,
procedure(I: Integer)
begin
PrintValue(I);
end
);
end;

关于delphi 变量值在循环中的线程中发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56516133/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com