如何从 TParallel.For 循环线程写入访问字符串变量?
How to write-access a string variable from a TParallel.For loop thread?
在 System.Threading.TParallel.For
循环中,我需要写访问在 TParallel.For
循环线程之外声明的字符串变量:
// Main thread:
procedure TForm2.GetWeather;
var
CurrentWeather: string;
begin
CurrentWeather := 'Current weather: ';
System.Threading.TParallel.For(1, 10,
procedure(idx: Integer)
begin
if IsRainy(idx) then
begin
// loop thread needs to write-access a mainthread-string-variable:
CurrentWeather := CurrentWeather + 'bad weather, ';
end;
end);
Self.Caption := CurrentWeather;
end;
但是根据文档,不应该这样做。而且 System.SyncObjs.TInterlocked
似乎没有写入字符串变量的方法。
那么在这种情况下我如何写入 CurrentWeather 变量?
Delphi 10.1.2 柏林
编辑:
根据 David Heffernan 的建议,我重写了代码 - 这是否正确?:
// Main thread:
procedure TForm2.GetWeather;
var
CurrentWeather: string;
ALock: TCriticalSection;
begin
CurrentWeather := 'Current weather: ';
ALock := TCriticalSection.Create;
try
System.Threading.TParallel.For(1, 10,
procedure(idx: Integer)
begin
if IsRainy(idx) then
begin
ALock.Enter;
try
CurrentWeather := CurrentWeather + 'bad weather, ';
finally
ALock.Leave;
end;
end;
end);
finally
ALock.Free;
end;
Self.Caption := CurrentWeather;
end;
您需要使用锁来修改像string
这样的复杂数据类型。这不能以原子方式完成。
如果您只定位 Windows,请使用 TCriticalSection
。对于针对其他平台的代码,您应该使用 TMonitor
.
另一种选择是使用 TThread.Queue
,例如像这样(假设您想要动态更新标题,而不是累积结果并在所有线程完成后显示它)
procedure TForm1.Button6Click(Sender: TObject);
begin
Caption := 'Current weather: ';
TParallel.For(1, 10,
procedure(idx: Integer)
begin
if IsRainy(idx) then
begin
// loop thread needs to write-access a mainthread-string-variable:
TThread.Queue(TThread.Current,
procedure
begin
Caption := Caption + 'bad weather, ';
end)
end;
end);
end;
在 System.Threading.TParallel.For
循环中,我需要写访问在 TParallel.For
循环线程之外声明的字符串变量:
// Main thread:
procedure TForm2.GetWeather;
var
CurrentWeather: string;
begin
CurrentWeather := 'Current weather: ';
System.Threading.TParallel.For(1, 10,
procedure(idx: Integer)
begin
if IsRainy(idx) then
begin
// loop thread needs to write-access a mainthread-string-variable:
CurrentWeather := CurrentWeather + 'bad weather, ';
end;
end);
Self.Caption := CurrentWeather;
end;
但是根据文档,不应该这样做。而且 System.SyncObjs.TInterlocked
似乎没有写入字符串变量的方法。
那么在这种情况下我如何写入 CurrentWeather 变量?
Delphi 10.1.2 柏林
编辑:
根据 David Heffernan 的建议,我重写了代码 - 这是否正确?:
// Main thread:
procedure TForm2.GetWeather;
var
CurrentWeather: string;
ALock: TCriticalSection;
begin
CurrentWeather := 'Current weather: ';
ALock := TCriticalSection.Create;
try
System.Threading.TParallel.For(1, 10,
procedure(idx: Integer)
begin
if IsRainy(idx) then
begin
ALock.Enter;
try
CurrentWeather := CurrentWeather + 'bad weather, ';
finally
ALock.Leave;
end;
end;
end);
finally
ALock.Free;
end;
Self.Caption := CurrentWeather;
end;
您需要使用锁来修改像string
这样的复杂数据类型。这不能以原子方式完成。
如果您只定位 Windows,请使用 TCriticalSection
。对于针对其他平台的代码,您应该使用 TMonitor
.
另一种选择是使用 TThread.Queue
,例如像这样(假设您想要动态更新标题,而不是累积结果并在所有线程完成后显示它)
procedure TForm1.Button6Click(Sender: TObject);
begin
Caption := 'Current weather: ';
TParallel.For(1, 10,
procedure(idx: Integer)
begin
if IsRainy(idx) then
begin
// loop thread needs to write-access a mainthread-string-variable:
TThread.Queue(TThread.Current,
procedure
begin
Caption := Caption + 'bad weather, ';
end)
end;
end);
end;