2017-02-17 6 views
5

일부 작업을 수행하는 스레드를 사용하는 프로그램이 있습니다. 스레드는 다른 스레드 (이 예제에서는 주 스레드)에 진행 상황을 알려야합니다.익명 프로 시저에서 로컬 변수를 처리하면 TThread.Queue로 전달됩니다.

동기화를 수행하려면()을 동기화하면 모든 것이 예상대로 작동합니다. 내가 메인 스레드와 동기화와에 대한 변수를 게시 목록에 넣어 경우 모든 단일 값의 제대로 내 목록 상자에 인쇄를 얻을 :

procedure TWorkerThread.Execute; 
var 
    i: Integer; 
begin 
    inherited; 

    for i := 1 to 1000 do 
    begin 
    Synchronize(
     procedure() 
     begin 
     FireEvent(i); 
     end); 
    end; 
end; 

출력 : 1, 2, 3, 4, 5. .. 1000

I 사용할 경우 ()의 출력이 예상과 동기화 수행 할 수

procedure TWorkerThread.Execute; 
var 
    i: Integer; 
begin 
    inherited; 

    for i := 1 to 1000 do 
    begin 
    Queue(
     procedure() 
     begin 
     FireEvent(i); 
     end); 
    end; 
end; 
,617을

출력 : 200, 339, 562, 934, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, 1001, [...]

여기 무슨 일 이죠? 내 이해에서 익명 프로 시저가 변수 "i"를 캡처해야합니까?

+0

추신 : 자주 UI를 업데이트하는 것이 의미가 없다는 것을 알고 있습니다. 나는 단지 익명의 메소드가 값을 잡아야한다는 사실을 알기 위해 가변 내용을 변경하는 것을 알고 싶다. –

+1

변수를 캡처합니다. 그러나 당신은 "가치"를 포착하려고 노력하고 있습니다. 따라서 루프의 반복마다 하나씩 새로운 변수를 만들어 캡처해야합니다. 이를 위해서는 새로운 스택 프레임이 필요하며 따라서 함수 호출이 필요합니다. 그러면 LURD의 대답으로 코드로 연결됩니다. –

답변

5

익명 프로시 저는 변수 참조를 캡처합니다. 이것은 익명 프로 시저가 실행될 때 값이 결정되지 않음을 의미합니다.

값을 포착하기 위해,이 같은 독특한 프레임으로 포장해야합니다 :

Type 
    TWorkerThread = class (TThread) 
    ... 
    function GetEventProc(ix : Integer): TThreadProcedure; 
    end; 

function TWorkerThread.GetEventProc(ix : Integer) : TThreadProcedure; 
// Each time this function is called, a new frame capturing ix 
// (and its current value) will be produced. 
begin 
    Result := procedure begin FireEvent(ix); end; 
end; 

procedure TWorkerThread.Execute; 
var 
    i: Integer; 
begin 
    inherited; 

    for i := 1 to 1000 do 
    begin 
    Queue(GetEventProc(i)); 
    end; 
end; 

Anonymous methods - variable capture versus value capture를 참조하십시오.

+0

그건 컴파일되지 않습니다 ... –

+0

'Queue (EventWithValue (i))'이어야하고'EventWithValue'는'TThreadProcedure'를 반환해야합니다. 적어도 그것은 내가 할 일이다. –

+0

[Delphi의 익명 메소드] (http://docwiki.embarcadero.com/RADStudio/en/Anonymous_Methods_in_Delphi), 특히 [익명 메소드 변수 바인딩] (http://docwiki.embarcadero.com/RADStudio/)을 읽어보십시오. en/Anonymous_Methods_in_Delphi # Anonymous_Methods_Variable_Binding). –