2017-05-04 225 views
1

当用户点击“取消”按钮或用户关闭/销毁表单时,我需要以最快的方式退出TParallel.For循环。只有TParallel.TLoopState.StopTParallel.TLoopState.Break状态退出TParallel.For循环的最快方法?

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; 

不幸的是,Embarcadero的文档:

Embarcadero Technologies公司目前没有任何额外的 信息,我与TParallel.TLoopState.StopTParallel.TLoopState.Break都尝试。

我也有这样的印象,即循环不会很快中断。有没有更好的办法?

+1

“如果从事件迭代所需本身迭代控制,迭代器的事件处理程序使用TParallel.TLoopState参数应该是一个当存在时,事件处理程序将给定一个TParallel.TLoopState的实例,从中可以监视来自Faulted,Stopped或ShouldExit的状态信息,或者可以使用Break或Stop方法来控制迭代循环本身。“ –

+0

这就是['TParallel.For'文档](http://docwiki.embarcadero.com/Libraries/en/System.Threading.TParallel.For) –

+0

这里是一个例子:[我怎样才能使用TTask .WaitForAny来自新的线程库?](http://stackoverflow.com/a/29078846/576719) –

回答

1

From the TParallel.For documentation

如果从事件迭代所需本身迭代控制,迭代器的事件处理程序应使用TParallel.TLoopState参数之一。当存在时,事件处理器将被给出TParallel.TLoopState的实例,从Faulted,StoppedShouldExit的状态信息可以被监控,或者迭代循环本身可以用方法BreakStop来控制。

跟踪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;