2013-06-02 1 views
2

OmniThreadLibrary 및 Delphi XE4를 사용하여 백그라운드에서 데이터를 처리하는 다중 스레드를 실행하여 기존 코드에 속도를 추가하는 방법을 모색하고 있습니다.OmniThreadLibrary의 ForEach가 주 스레드를 차단하는 이유는 무엇입니까?

아래 절차를 호출 할 때 응용 프로그램 GUI는 모든 스레드가 완료 될 때까지 입력 처리를 중지합니다. 제 이해는 .NoWait을 사용하면 스레드가 실행 중일 때에도 프로 시저가 종료되도록해야합니다.

procedure Test(input: TStringList; output: TList<TMaintFore>); 
var 
    outQueue: IOmniBlockingCollection; 
    transaction: TOmniValue; 
begin 
    outQueue := TOmniBlockingCollection.Create; 
    Parallel.ForEach(0, input.Count - 1) 
    .NoWait 
    .Into(outQueue) 
    .Execute(
     procedure(const value: integer; var result: TOmniValue) 
     begin 
     result := TMaintFore.Create(input[value]); 
     end 
    ); 
end; 

ForEach 루프에 대한 나의 이해가 부정확합니다. 배경 처리를 위해 대체 방법을 사용해야한다고 제안 했습니까? OmniThreadLibrary의 올바른 사용에 대한 제안은 인정됩니다.

답변

10

Parallel.ForEach에서 반환 된 인터페이스를 전역 (양식 등) 변수에 저장하고 ForEach가 실행을 완료 할 때만이를 파기해야합니다.

예에서 ForEach의 결과는 테스트 절차가 종료 될 때 파기되는 임시 변수에 저장됩니다. ForEach 소멸자는 모든 작업이 완료 될 때까지 기다리고 프로그램을 차단합니다.

작업 완료시 foreach 인터페이스를 파괴하는 가장 안전한 방법은 OnStop 메서드를 사용하고 명령에서 주 스레드에 명령을 대기시키는 것입니다.

var 
    loop: IOmniParallelLoop<integer>; 

loop := Parallel.ForEach(1, N).NoWait; 
loop.OnStop(
    procedure (const task: IOmniTask) 
    begin 
    task.Invoke(
     procedure 
     begin 
     // do anything 
     loop := nil; 
     end); 
    end); 
loop.Execute(
    procedure (const value: integer) 
    begin 
    ... 
    end); 

이것은 the wiki에 설명되어 있습니다.

+1

작업 완료시 알림을받을 수 있습니까? –

+0

위 답변은 – gabr

+1

감사합니다. 그게 내 자신의 교육에 대한 더 많은 질문이었습니다. 제가 당신을 가지고있을 때 보았습니다! ;-)하지만 나는 asker가 똑같은 것을 궁금해 할 것 같아. –