Най-бързият начин за излизане от цикъл TParallel.For?

Трябва да изляза от 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;

За съжаление документацията на Embarcadero за TParallel.TLoopState.Stop и TParallel.TLoopState.Break гласи само:

В момента Embarcadero Technologies не разполага с допълнителна информация.

Също така имам впечатлението, че цикълът не се прекъсва много бързо. Има ли по-добър начин?


person user1580348    schedule 04.05.2017    source източник
comment
Ако е необходимо управление на самата итерация от събитието на итератора, манипулаторът на събитието на итератора трябва да бъде такъв, използващ параметъра TParallel.TLoopState. Когато е налице, на манипулатора на събитието ще бъде даден екземпляр на TParallel.TLoopState, от който информацията за състоянието от Faulted, Stopped или ShouldExit може да бъде наблюдавана, или самият итерационен цикъл може да се контролира с методите Break или Stop.   -  person LU RD    schedule 04.05.2017
comment
И това е посочено в TParallel.For документация   -  person Remy Lebeau    schedule 04.05.2017
comment
Ето един пример: Как мога да използвам TTask.WaitForAny от новата библиотека с нишки?   -  person LU RD    schedule 04.05.2017
comment
За да спрете бързо други задачи с нишки, вашият DoProcessValue() трябва редовно да проверява свойството Stopped.   -  person LU RD    schedule 04.05.2017
comment
Използвал съм прост TEvent, когато потребителят анулира зададеното си за signaled и цикълът проверява това и излиза. Има толкова много, че в момента няма допълнителна информация.. струва си да следвате.   -  person FredS    schedule 05.05.2017


Отговори (1)


От документацията TParallel.For:

Ако е необходимо управление на самата итерация от събитието на итератора, манипулаторът на събитието на итератора трябва да бъде такъв, използващ параметъра 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;
person Johan    schedule 05.05.2017