2017-05-04 4 views
1

Ich muss eine TParallel.For Schleife auf schnellstmögliche Weise beenden, wenn der Benutzer auf eine Schaltfläche Abbrechen klickt oder wenn der Benutzer das Formular schließt/zerstört. Ich habe beide versucht, mit TParallel.TLoopState.Stop und TParallel.TLoopState.Break:Schnellster Weg zum Beenden einer TParallel.For-Schleife?

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; 

Leider die Embarcadero Dokumentation für TParallel.TLoopState.Stop und TParallel.TLoopState.Break Staaten nur:

Embarcadero Technologies verfügt derzeit nicht über zusätzliche Informationen.

Ich habe auch den Eindruck, dass die Schleife nicht sehr schnell unterbrochen wird. Gibt es einen besseren Weg?

+1

„Wenn die Kontrolle über die Iteration selbst aus dem Iterator Ereignisse benötigt wird, sollte der Iterator Ereignishandler man den TParallel.TLoopState Parameter verwendet werden, wenn vorhanden, der Event-Handler wird eine Instanz von TParallel.TLoopState erhalten, aus der Statusinformationen von Faulted, Stopped oder ShouldExit überwacht werden können oder die Iterationsschleife selbst mit den Methoden Break oder Stop gesteuert werden kann. " –

+0

Und das steht in der ['TParallel.For'-Dokumentation] (http://docwiki.embarcadero.com/Libraries/en/System.Threading.TParallel.For) –

+0

Hier ist ein Beispiel: [Wie kann ich TTask verwenden .WaitForAny aus der neuen Threading-Bibliothek?] (Http://stackoverflow.com/a/29078846/576719) –

Antwort

1

From the TParallel.For documentation:

Wenn die Kontrolle über die Iteration selbst aus dem Iterator Ereignisse benötigt wird, sollten die Iterator-Ereignishandler einen mit dem TParallel.TLoopState Parameter sein. Wenn vorhanden, erhält der Event-Handler eine Instanz von TParallel.TLoopState, aus der Zustandsinformationen von Faulted, Stopped oder ShouldExit überwacht werden können, oder die Iterationsschleife selbst kann mit den Methoden Break oder Stop gesteuert werden.

Die Art und Weise den Überblick über LoopState zu halten, ist eine Methode mit der folgenden Signatur zu verwenden:

TIteratorStateEvent = 
    procedure (Sender: TObject; AIndex: Integer; const LoopState: TLoopState) of object; 

Oder seine anonyme Version verwenden:

class function &For(AStride, ALowInclusive, AHighInclusive: Integer; 
const AIteratorEvent: TProc<Integer, TLoopState>; APool: TThreadPool): TLoopResult; 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

Wenn die Dokumentation der einfachste Weg, schlägt fehl ist es, den Quellcode für die Klasse zu suchen, oder Codevervollständigung die Arbeit zu machen.

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; 

. Beispiel:

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; 
Verwandte Themen