2017-12-08 2 views
1

배열 작업을 수행하는 일련의 작업이 있습니다. 나는 배열을 통해 반복하고 각각에 대해 작업을 시작하려고합니다.루프 내부의 컨텍스트를 Delphi에서 TTask.IFuture로 전달하는 방법은 무엇입니까?

다음 예제는 사소한 것입니다 (제곱 계산).

1 * 1 = 1. Future<Integer> = 16 - MISMATCH 
2 * 2 = 4. Future<Integer> = 100 - MISMATCH 
3 * 3 = 9. Future<Integer> = 100 - MISMATCH 
4 * 4 = 16. Future<Integer> = 100 - MISMATCH 
5 * 5 = 25. Future<Integer> = 100 - MISMATCH 
6 * 6 = 36. Future<Integer> = 100 - MISMATCH 
7 * 7 = 49. Future<Integer> = 100 - MISMATCH 
8 * 8 = 64. Future<Integer> = 100 - MISMATCH 
9 * 9 = 81. Future<Integer> = 100 - MISMATCH 
10 * 10 = 100. Future<Integer> = 100 - match 

어떻게 내 목표를 달성 할 수 다음과 같이

program FutureSquares; 

{$APPTYPE CONSOLE} 

{$R *.res} 

uses 
    System.SysUtils, 
    System.Threading, 
    System.Classes; 
const 
    nums: array[0..9] of Integer = (1,2,3,4,5,6,7,8,9,10); 
var 
    i, contextIndex: Integer; 
    f: array[0..9] of ITask; 
    answer, futureAnswer: Integer; 
    matchDisplay: string; 
    futureFunc: TFunc<Integer>; 
begin 

    try 
    for i := Low(f) to High(f) do 
    begin 
     contextIndex := i; 

     futureFunc := function: Integer 
     begin 
      Sleep(Random(1000)); 
      Result := nums[contextIndex]*nums[contextIndex]; // trying because a reference to it is captured. How to capture the actual value? 
     end; 

     f[i] := TTask.Future<Integer>(futureFunc); 
     f[i].Start; 
    end; 

    //verify results in sequential manner 
    for i := Low(f) to High(f) do 
    begin 
     answer := nums[i]*nums[i]; 
     futureAnswer := IFuture<Integer>(f[i]).Value; 
     if futureAnswer = answer then 
     matchDisplay := 'match' 
     else 
     matchDisplay := 'MISMATCH'; 
     writeln(Format('%d * %d = %d. Future<Integer> = %d - %s', [nums[i],nums[i],answer, futureAnswer, matchDisplay])); 
    end; 

    readln; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
end. 

프로그램의 출력은?

TTask.Future는 유용 할 컨텍스트를 전달할 수 없다는 점에 유의하십시오.

답변

3

익명 메소드에서 변수가 아니라 값을 캡처해야합니다. 이렇게하는 가장 쉬운 방법은 익명 메소드를 독립형 함수에 넣고 캡처하려는 인덱스를 전달하는 것입니다. 이렇게하면 변수 대신 값이 캡처됩니다. 당신이 futureFunc의 임무를 수행 할 때

function CaptureFuture(const aTheIndex: Integer): TFunc<Integer>; 
begin 
    Result := function: Integer 
    begin 
     Sleep(Random(1000)); 
     Result := nums[aTheIndex]*nums[aTheIndex]; // trying because a reference to it is captured. How to capture the actual value? 
    end; 
end; 

그리고, 당신의 코드는 다음과 같습니다

for i := Low(f) to High(f) do 
begin 
    futureFunc := CaptureFuture(i); 

    f[i] := TTask.Future<Integer>(futureFunc); 
    f[i].Start; 
end; 

이 원하는 결과를 줄 것이다 :

1 * 1 = 1. Future<Integer> = 1 - match 
2 * 2 = 4. Future<Integer> = 4 - match 
3 * 3 = 9. Future<Integer> = 9 - match 
4 * 4 = 16. Future<Integer> = 16 - match 
5 * 5 = 25. Future<Integer> = 25 - match 
6 * 6 = 36. Future<Integer> = 36 - match 
7 * 7 = 49. Future<Integer> = 49 - match 
8 * 8 = 64. Future<Integer> = 64 - match 
9 * 9 = 81. Future<Integer> = 81 - match 
10 * 10 = 100. Future<Integer> = 100 - match 

이 질문을 참조하십시오 변수 대 값 캡처에 대한 자세한 내용은 Anonymous methods - variable capture versus value capture

관련 문제