Ich baue in Rad Studio XE7 eine Firemonkey-App, bei der ich mit einem einzigen Klick mehrere (etwa 7) Web-Service-Aufrufe mit TRestRequest machen muss. Jeder Webservice gibt ein json-Objekt zurück, das dann das Dataset auffüllt. Ich suche nach einem Weg, um diese Anrufe gleichzeitig und nicht über die Benutzeroberfläche der App zu sperren.
Welchen Weg empfehlen Sie, dies zu tun? Ich habe gesehen, dass Embarcadero neue Aufgaben- und Funktionsfunktionen für das Threading eingeführt hat, aber ich bin mir immer noch nicht sicher, ob wir das und wie verwenden können. Außerdem habe ich gesehen, dass es eine Funktion gibt, um TRestRequest asynchron mit dieser Funktion auszuführen:
%Vor%Ich kann jedoch keine Dokumentation darüber finden, wie man diese Methode verwendet und was sie tut.
Jede Eingabe wird sehr geschätzt.
Die Methode ExecuteAsync(ACompletionHandler: TCompletionHandler = nil; ASynchronized: boolean = true; AFreeThread: boolean = true)
ist in der Tat der richtige Weg. Wie der Name schon sagt, ist es asynchron; Das bedeutet, dass Ihr Programm nach dem Absetzen der Anforderung oder sogar nach dem Absetzen mehrerer Anfragen weiterhin reagiert.
Es ist jedoch wichtig, dass Sie diese unterschiedlichen Anforderungen von verschiedenen Objektinstanzen auslösen. Wenn Sie eine ExecuteAsync
von einer TRESTRequest
-Instanz auslösen, die bereits eine ExecuteAsync
ausführt, wird die neue Anforderung die bestehende Anfrage in die Quere kommen. Sie müssen für jeden parallelen Aufruf eine separate Instanz TRESTRequest
erstellen.
Beachten Sie, dass der erste Parameter eine Prozedur ist; Sie übergeben ein Verfahren Ihrer Wahl als diesen Parameter. Die einzige Voraussetzung ist, dass das Verfahren die richtige Unterschrift hat; In diesem Fall ist es eine Prozedur, die keine Parameter hat.
Die ExecuteAsync-Methode ist in REST.Client
definiert. (Ich habe Delphi XE-10.1. Berlin, so hat es einen zusätzlichen Parameter, ACompletionHandlerWithError
- der bei einem Fehler aufgerufen wird. Das Prinzip bleibt jedoch gleich).
Werfen wir einen Blick darauf:
%Vor% In diesem Fall wird ein neuer Thread erstellt, in dem der REST-Request ausgeführt wird. Wenn die Antwort eintrifft, wird sie von ACompletionHandler
behandelt.
Standardmäßig läuft ACompletionHandler
auf dem neuen Thread, der von ExecuteAsync
erstellt wurde. Wenn Sie möchten, dass es im Hauptthread ausgeführt wird, sollten Sie ASynchronized
auf true
setzen.
Aber wie erhalten Sie Zugriff auf diese Antwort und machen sie für den Rest Ihres Programms zugänglich?
Die TRESTRequest-Klasse von FireMonkey hat eine Eigenschaft Response
, die sich auf das TRESTResponse-Objekt bezieht, das die Antwort des Servers auf unsere Anfrage enthält.
Leider werden weder das TRESTRequest- noch das TRESTResponse-Objekt an unseren CompletionHandler übergeben!
Also müssen wir dem CompletionHandler irgendwie diese Informationen geben. Glücklicherweise können wir eine Methode als CompletionHandler verwenden.
Nehmen wir an, dass die Klasse, die die resultierenden Daten verarbeiten wird, DataOwner
heißt. Unser Ziel ist, dass DataOwner
Zugriff auf die TRESTResponse-Instanz hat, die unserer TRESTRequest-Instanz zugeordnet ist.
Der einfachste Weg dazu ist TRESTRequest und / oder TRESTResponse ein Mitglied von DataOwner
zu werden.
Nehmen wir an, Ihre Anforderung wurde von einer TRESTRequest-Instanz mit dem Namen MyRESTRequest
ausgelöst und von einer Funktion processResponse
verarbeitet. Sie würden den folgenden Code verwenden:
Wenn Sie mehrere Anfragen parallel absetzen wollen, müssen Sie dieses Muster mehrmals verwenden. Leider haben wir in unseren Completion Handlern keinen direkten Zugriff auf die TRESTRequest-Instanz oder die TRESTResponse-Instanz, da wir die Buchhaltung selbst durchführen müssen. Mit anderen Worten, es liegt am Programmierer, sicherzustellen, dass der Vervollständigungshandler das richtige Response-Objekt verarbeitet.
Tags und Links multithreading delphi rest asynchronous