Самый быстрый способ выйти из цикла 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
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