我必须在一段时间内在匿名线程中调用函数
我的示例函数就是这样,仅用于打印输出:
function processPureTmFrame(rowFrame : string;tmDataGroupRef:string ):string;
TThread.Synchronize(nil,
procedure
begin
form2.Memo1.Lines.Add( tmSlitFrame );
end
);
end;
当我这样调用函数时:
代码1
while tmBody.Length>0 do
begin
tmBodyFrameLength := ((hextodec( copy(tmBody,11,2) )+6)*2)+2;
tmSplitFrame := copy(tmBody , 1 , tmBodyFrameLength );
delete( tmBody, 1, tmBodyFrameLength );
myThread := TThread.CreateAnonymousThread(
procedure
begin
processPureTmFrame( tmSplitFrame , tmDataGroupRef );
end);
myThread.Start;
end;
在循环的第一个周期中,输出丢失
但是当我在没有线程的情况下调用代码时,一切都很好!
代码2
while tmBody.Length>0 do
begin
tmBodyFrameLength := ((hextodec( copy(tmBody,11,2) )+6)*2)+2;
tmSplitFrame := copy(tmBody , 1 , tmBodyFrameLength );
delete( tmBody, 1, tmBodyFrameLength );
processPureTmFrame( tmSplitFrame , tmDataGroupRef );
end;
正确的输出必须是这样
0851C007000C010100000007581850C001F116
0836C0BE001003627169DCA200000000000090D72AACAF
0814C0B6001C03197169DCA31901E2041211131D001F00001F1E1C1F1F1E1E1E0077AA
0814C0B7001E03197169DCA31902FE00540F0000000000000000000000000000000000E238
0814C0B8000B03197169DCA31903FE01384E
0817C0B9000D05017169DCA3E6010190B03F042D
0852C000000B036200000000FAFFFFBF16A3
0852C001000B036200000001F4FF00000000
但是在线程(代码1)中调用时就像
0836C0BE001003627169DCA200000000000090D72AACAF
0814C0B6001C03197169DCA31901E2041211131D001F00001F1E1C1F1F1E1E1E0077AA
0814C0B7001E03197169DCA31902FE00540F0000000000000000000000000000000000E238
0814C0B8000B03197169DCA31903FE01384E
0817C0B9000D05017169DCA3E6010190B03F042D
0852C000000B036200000000FAFFFFBF16A3
0852C001000B036200000001F4FF00000000
没有线程(代码2)的输出没问题
注释#1 :我没有收到类似的错误消息:
系统错误。代码:1400。无效的窗口句柄或其他任何东西
注释#2 :正如我所说的,只是第一个周期,而没有发送到新线程。其他行正在发送和处理就很好了!
答案 0 :(得分:4)
问题在于匿名方法捕获变量。由于捕获了变量,因此其值在主循环中会更改。本质上,所有线程共享相同的变量。线程与主循环并行运行,并且没有排序约束。因此,在您的线程之一有机会使用该值之前,主循环很可能会修改捕获的变量。
您的代码将与值捕获(而不是变量捕获)一起使用。不直接支持值捕获,但是易于模拟相同的效果。参见Anonymous methods - variable capture versus value capture。
我要评论一下,尽管此线程代码将比串行代码慢。您希望实现什么?