如果我运行此代码,结果会出乎意料,因为线程中的字符串没有正确的值:
procedure TMain.FollowBose(Speakername: string; NewState: Boolean);
{..}
procedure TMain.ProcessRoomMotionResponse(Rooms: TJSONArray; Response: TJSONObject);
var
ParamName1: string;
ParamName2: string;
Room: tJSONValue;
RoomData: TJSONObject;
Roomname: string;
Motion: Boolean;
begin
if Assigned(Rooms) then begin
ParamName1 := 'Room';
ParamName2 := 'Motion';
for Room in Rooms do begin
RoomData := Room as TJSONObject;
if Assigned(RoomData.Values[ParamName1]) and Assigned(RoomData.Values[ParamName2]) then begin
Roomname := RoomData.Values[ParamName1].Value;
Motion := RoomData.Values[ParamName2].AsType<Boolean>;
LogWrite('Launching sub for ' + Roomname + '-FollowUp.', Debug);
TThread.CreateAnonymousThread(
procedure
begin
FollowUp(Roomname, Motion);
end).Start;
end;
end;
end;
end;
由于字符串很特殊,这是可以预料到的吗?
1 个回答
1
这与具体的字符串无关,而是与匿名过程如何捕获变量有关。这是有记录的行为:
特别是,根据“变量绑定机制”部分:
如果匿名方法引用其主体中的外部局部变量,则该变量将被“捕获”。捕获意味着延长变量的生命周期,使其与匿名方法值一样长,而不是随着其声明例程而消亡。请注意,变量捕获捕获的是变量,而不是值。如果通过构造匿名方法捕获变量的值发生变化,则匿名方法捕获的变量的值也会发生变化,因为它们是相同的变量,具有相同的存储空间。捕获的变量存储在堆上,而不是堆栈上。
您与所有线程共享相同的局部Roomname
变量Motion
,而不是为每个线程提供自己的变量副本。当循环运行时,您正在更改所有线程共享的变量的值。
试试这个:
procedure TMain.ProcessRoomMotionResponse(Rooms: TJSONArray; Response: TJSONObject);
var
ParamName1: string;
ParamName2: string;
Room: tJSONValue;
RoomData: TJSONObject;
Roomname: string;
Motion: Boolean;
procedure DoFollowUp(ARoomName: string; AMotion: Boolean);
begin
LogWrite('Launching sub for ' + ARoomName + '-FollowUp.', Debug);
TThread.CreateAnonymousThread(
procedure
begin
FollowUp(ARoomName, AMotion);
end).Start;
end;
begin
if Assigned(Rooms) then begin
ParamName1 := 'Room';
ParamName2 := 'Motion';
for Room in Rooms do begin
RoomData := Room as TJSONObject;
if Assigned(RoomData.Values[ParamName1]) and Assigned(RoomData.Values[ParamName2]) then begin
Roomname := RoomData.Values[ParamName1].Value;
Motion := RoomData.Values[ParamName2].AsType<Boolean>;
DoFollowUp(Roomname, Motion);
end;
end;
end;
end;
这样,每个线程都会捕获自己的输入参数副本DoFollowUp()
,而不是捕获 的局部变量ProcessRoomMotionResponse()
。
1
-
哈哈,这个“DoFollowUp”改变了一切! 😀 谢谢
–
|
|