2017-05-04 61 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;