当用户单击“取消”按钮或用户关闭/销毁表单时,我需要以最快的方式退出 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 does not currently have any additional information.
我还有这样的印象:循环不会很快中断。有更好的办法吗?
最佳答案
From the TParallel.For
documentation :
If control of the iteration itself is needed from the iterator event, the iterator event handler should be one using the
TParallel.TLoopState
parameter. When present, the event handler will be given an instance ofTParallel.TLoopState
from which state information fromFaulted
,Stopped
, orShouldExit
can be monitored, or the iteration loop itself can be controlled with theBreak
orStop
methods.
跟踪 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;
关于multithreading - 退出 Parallel.For 循环的最快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43790289/