Ich selbst bin ein Fan vom BeginInvoke/EndInvoke Pattern.
Ich kann dadurch X Operationen asynchron starten, andere Dinge erledigen, und dann wenn ich das Ergebnis brauche, wartet der Code halt auf den Rückgabewert oder er hat ihn schon.
Das ganze lässt sich auch so verpacken, dass man sich eine Factory für Delegates baut, die dann entweder warten oder den bestehenden Wert zurück geben.
Um nicht soviel drumrum posten zu müssen, habe ich es mal nur mit lokalen Delegates gelöst: (Kein Delphi Code!)
Delphi-Quellcode:
var r : Random := new Random();
var myCall := method(parameter1, parameter2 : String) : Integer;
begin
Thread.Sleep(5000);
exit r.Next(0, 1000);
end;
var getAsyncCall := method(parameter1, parameter2 : String) : Func<Integer>;
begin
var resultRef := new class(Value := default(nullable Integer));
var getValue : AsyncCallback := method(ar : IAsyncResult);
begin
locking resultRef do
if not assigned(resultRef.Value) then
resultRef.Value := myCall.EndInvoke(ar);
end;
var call := myCall.BeginInvoke(parameter1,
parameter2,
getValue,
nil);
result := method : Integer;
begin
getValue(call);
exit valueOrDefault(resultRef.Value);
end;
end;
var async1 := getAsyncCall('abc', 'def');
var async2 := getAsyncCall('ghi', 'jkl');
// do soemthing...
Thread.Sleep(2500);
var result1 := async1();
var result2 := async2();
var result3 := async1();
Mit
Futures wird das dann schon zu einem totalen no-brainer.
Delphi-Quellcode:
var future1 := async myCall('abc', 'def');
var future2 := async myCall('ghi', 'jkl');