在以下情况下,由匿名线程读取的DoSomething中的AValue值是否保证是“可读的”?即,我期望的价值?对我来说,我不认为DoSomething在线程实际执行之前就超出范围(即返回)(可以通过意识到x:= 2总是在线程开始之前执行来轻松看出-尽管我猜是与线程有关的)所有投注均关闭,并且我的线程可能在DoSomething返回之前执行)。
我只问是因为我在测试中从未遇到过AValue不等于1(也就是传入的值)的情况,所以我想知道是否对过程和/或线程保留了一些隐式引用(同样不太可能CreateAnonymousMethod只是创建一个TThread后代的实例(TAnonymousThread),并调用我的匿名“ execute”方法)。我猜是一样的,因为在这种有限的情况下,没有任何东西会覆盖存储AValue的内存位置。
procedure TForm2.Button1Click(Sender: TObject);
var
x: Integer;
begin
x := 1;
DoSomething(x);
x := 2;// this line is only here for the purposes of placing a break point
end;
procedure TForm2.DoSomething(AValue: Integer);
begin
TThread.CreateAnonymousThread(
procedure
var
y: Integer;
begin
y := AValue;
if y = 1 then
MessageBox(0, 'Same', 'Value', MB_ICONINFORMATION or MB_OK)
else
MessageBox(0, 'Different', 'Value', MB_ICONINFORMATION or MB_OK)
end).Start;
end;
编辑只是为了验证,我想知道在匿名线程的上下文中捕获局部变量是否安全。
您正在按值传递x。这意味着x的值在您调用时被复制DoSomething()
。
因此,无论何时执行匿名线程,它都不会引用x。线程使用了一个捕获的变量,该变量用的原始值初始化x
。
换句话说,匿名线程无法查看您是否稍后在ButtonClick1
事件中更改了x 。
注意,如果AValue
在DoSomething()
构造匿名线程之后更改local in ,这将影响线程的结果。
procedure TForm2.DoSomething(AValue: Integer);
begin
TThread.CreateAnonymousThread(
procedure
var
y: Integer;
begin
y := AValue;
if y = 1 then
MessageBox(0, 'Same', 'Value', MB_ICONINFORMATION or MB_OK)
else
MessageBox(0, 'Different', 'Value', MB_ICONINFORMATION or MB_OK)
end).Start;
AValue := 3; // <-- This value will likely be seen by the anonymous thread.
end;
如果要避免这种情况,可以捕获如下AValue
值:
procedure TForm4.DoSomething(AValue: Integer);
function CaptureValue( y: Integer) : TProc;
begin
Result :=
procedure
begin
if y = 1 then
MessageBox(0, 'Same', 'Value', MB_ICONINFORMATION or MB_OK)
else
MessageBox(0, 'Different', 'Value', MB_ICONINFORMATION or MB_OK)
end;
end;
var
p : TProc;
begin
p := CaptureValue(AValue);
TThread.CreateAnonymousThread( p)
.Start;
AValue := 3; // <-- The anonymous method is unaffected by this change !
end;
该文档解释说,外部局部变量AValue是通过匿名方法的引用来捕获的:
如果匿名方法在其主体中引用外部局部变量,则该变量将被“捕获”。捕获意味着延长变量的生存期,以使它的生存时间与匿名方法的值一样长,而不是死于其声明例程。请注意,变量捕获捕获变量,而不是值。如果通过构造匿名方法捕获变量后其值发生变化,则匿名方法捕获的变量值也将发生变化,因为它们是具有相同存储的相同变量。捕获的变量存储在堆中,而不是堆栈中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句