Delphi async / warte auf Emulation

    C # hat das Konstrukt async / await eingeführt. Das folgende Beispiel zeigt, wie Sie dieses Verhalten in Delphi erreichen.

    Ich gehe davon aus, dass Sie mit Async / Warten vertraut sind. Es ist praktisch für Vorgänge, bei denen keine Prozessorbeteiligung erforderlich ist. Der Prozessor startet gerade den Betrieb und kommt von außen, um sein Ende zu melden. Ein gutes Beispiel ist ein Aufruf eines Webservers. Angenommen, unser Webserver kann zwei Operationen ausführen: Addition und Multiplikation.
            async Task MakeAsyncTask_Plus(int aArg1, int aArg2, int aDurationMs)
            {   // эмуляция вызова на веб сервер
                await Task.Delay(aDurationMs);
                return aArg1 + aArg2;
            }
            async Task MakeAsyncTask_Mult(int aArg1, int aArg2, int aDurationMs)
            {   // эмуляция вызова на веб сервер
                await Task.Delay(aDurationMs);
                return aArg1 * aArg2;
            }
    

    Der Client möchte den Ausdruck (1 + 2) * (3 + 4) auswerten. Weil Die Ergebnisse der Ergänzungen sind unabhängig und können gleichzeitig durchgeführt werden:
            async void CalcAsync()
            {
                Task aPlus1 = MakeAsyncTask_Plus(1, 2, 2000);      // 1
                Task aPlus2 = MakeAsyncTask_Plus(3, 4, 2000);      // 2
                int aArg1 = await aPlus1;                                // 3
                int aArg2 = await aPlus2;                                // 4
                Task aMult = MakeAsyncTask_Mult(aArg1, aArg2, 1000); // 5
                int aRes = await aMult;                                  // 6
                Log(string.Format("{0} * {1} = {2}", aArg1, aArg2, aRes));
            }
    

    Vor der Zeile "// 3" (das erste Warten) wird die Methode wie gewohnt ausgeführt. Beim Warten wird die Methode beendet und am Ende des Vorgangs (bis zum nächsten Warten) fortgesetzt. Die Steuerung wird vom Nachrichtenmechanismus oder in einem anderen Thread übertragen - sie wird in der Umgebung konfiguriert. In C # wird dies vom Compiler erreicht. In Delphi kann mit Fibre ein ähnliches Verhalten für einen einzelnen Thread erzielt werden. Eine ähnliche Methode würde aussehen wie:
    procedure TCalcAsync.Execute;
    var
      aPlus1: TAsyncTask;
      aPlus2: TAsyncTask;
      aMult: TAsyncTask;
      aArg1, aArg2: Integer;
      aRes: Integer;
    begin
      aPlus1 := nil;
      aPlus2 := nil;
      aMult := nil;
      try
        aPlus1 := TAsyncTask_Plus.Create(Self, 1,{+}2, 2000{ms});
        aPlus2 := TAsyncTask_Plus.Create(Self, 3,{+}4, 2000{ms});
        aArg1 := aPlus1.Await;
        aArg2 := aPlus2.Await;
        aMult := TAsyncTask_Mult.Create(Self, aArg1,{*}aArg2, 1000{ms});
        aRes := aMult.Await;
        Example.Log('%d * %d = %d', [aArg1, aArg2, aRes]);
      finally
        aMult.Free;
        aPlus2.Free;
        aPlus1.Free;
      end;
    end;
    

    Das Beispiel funktioniert für Delphi 2007, XE2, XE8.

    Jetzt auch beliebt: