当用户单击“取消”按钮或用户关闭/销毁表单时,我需要以最快的方式退出TParallel.For
循环。我已尝试使用TParallel.TLoopState.Stop
和TParallel.TLoopState.Break
:
var
BreakCondition: Boolean;
procedure TForm2.DoStartLoop;
begin
BreakCondition := False;
System.Threading.TParallel.For(1, 50,
procedure(idx: Integer; LS: TParallel.TLoopState)
begin
if BreakCondition then
begin
//LS.&BREAK;
LS.STOP;
//EXIT;
end
else
DoProcessValue(idx);
end);
end;
不幸的是,TParallel.TLoopState.Stop
和TParallel.TLoopState.Break
的Embarcadero文档仅指出:
Embarcadero Technologies目前没有任何额外的补充 信息。
我还认为循环不会很快中断。还有更好的方法吗?
答案 0 :(得分:2)
From the TParallel.For
documentation:
如果迭代器事件需要控制迭代本身,则迭代器事件处理程序应该是使用
TParallel.TLoopState
参数的处理程序。如果存在,将为事件处理程序提供TParallel.TLoopState
的实例,可以从中监视来自Faulted
,Stopped
或ShouldExit
的状态信息,或者迭代循环本身可以使用Break
或Stop
方法进行控制。
跟踪LoopState的方法是使用具有以下签名的方法:
TIteratorStateEvent =
procedure (Sender: TObject; AIndex: Integer; const LoopState: TLoopState) of object;
或使用其匿名版本:
class function &For(AStride, ALowInclusive, AHighInclusive: Integer;
const AIteratorEvent: TProc<Integer, TLoopState>; APool: TThreadPool): TLoopResult;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
如果文档失败,最简单的方法是搜索类的源代码,或者让代码完成工作。
TLoopState = class
private [...]
public
procedure Break;
procedure Stop;
function ShouldExit: Boolean; <<-- this looks useful
property Faulted: Boolean read GetFaulted;
property Stopped: Boolean read GetStopped; <<-- or this
property LowestBreakIteration: Variant read GetLowestBreakIteration;
end;
示例:
procedure TForm1.btnParallelForClick(Sender: TObject);
var
Tot: Integer;
SW: TStopwatch;
begin
try
// counts the prime numbers below a given value
Tot :=0;
SW :=TStopWatch.Create;
SW.Start;
//Use a method that supports LoopState
TParallel.For(2,1,Max,procedure(I:Int64; State: TLoopState)
begin
//check loopstate every now and again.
if State.ShouldExit then exit;
if IsPrime(I) then TInterlocked.Increment(Tot);
end);
SW.Stop;
Memo1.Lines.Add(Format('Parallel For loop. Time (in milliseconds): %d - Primes found: %d', [SW.ElapsedMilliseconds,Tot]));
except on E:EAggregateException do
ShowMessage(E.ToString);
end;
end;