Swift Problematik Asynchrone Ergebnisse abrufen und Mitteilung ausgeben

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Swift Problematik Asynchrone Ergebnisse abrufen und Mitteilung ausgeben

    Hallo,

    folgende Problematik stellt sich mir. Vom Main-Thread werden verschiedene asynchrone Threads gestartet, diese liefern nach Abarbeitung ein Ergebnis welches in Klassenvariablen (x1, x2 usw.) gespeichert werden.

    Hinweis: Die asynchron aufgerufenen Threads bzw. dessen Funktionen darf ich nicht verändern bzw. ergänzen.

    Es soll nun eine Meldung ausgegeben werden, wenn alle asychronen Threads beendet wurden.

    Ich benötige nun ein paar Anregungen wie so eine Funktion programmtechnisch aufgebaut sein müsste.



    Vielen Dank mal vorab.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von OSXDev () aus folgendem Grund: Hinweis

  • Hier will jetzt mal das Ei klüger sein als die Henne :) aber wäre nicht eine TaskGroup eine Möglichkeit, bei der Du mittels for await ... in ... auf ein Gesamtergebnis wartest? Bei unterschiedlichen Rückgabetypen muss man wohl per enum tricksen, aber so weit habe ich nicht geschaut.

    Oder mittels Semaphoren?

    Nur als Denkanstoß...
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • MyMattes schrieb:

    Hier will jetzt mal das Ei klüger sein als die Henne :) aber wäre nicht eine TaskGroup eine Möglichkeit, bei der Du mittels for await ... in ... auf ein Gesamtergebnis wartest? Bei unterschiedlichen Rückgabetypen muss man wohl per enum tricksen, aber so weit habe ich nicht geschaut.

    Oder mittels Semaphoren?

    Nur als Denkanstoß...
    Hi Mattes,

    danke für Deine Anregung. Jedoch habe ich nur Beispiele gefunden in der jeweils nur eine Funktion (laden von Fotodateien) aufgerufen wurde, welche zwar bei jedem Aufruf ein neues Ergebnis lieferte, jedoch muss ich mehrere Funktionen aufrufen die jeweils einen Datentyp (String) zu nicht definierten Zeiten zurückgeben. Möglicherweise sehe ich auch den Wald vor lauter Bäumen nicht mehr. Wäre prima wenn Du mir eine Quelle oder ein Beispiel nennen könntest, dass für meinen Fall passen würde.

    Danke mal vorab.
  • MCDan schrieb:

    Wie werden denn die asynchrone Threads gestartet?

    Wenn Du diese per Grand Central Dispatch (GCD) startest, dann kannst Du Dich informieren lassen, wenn alle Tasks beendet sind.

    Anbei mal ein Beispiel dass ich gefunden habe:

    Quellcode

    1. let bResult = DispatchQueue(label: "concurrentQueue_1", qos: .background, attributes: .concurrent)

    Vielleicht bin ich zu müde, aber wo in diesem Aufruf trage ich den Funktionsnamen ein? Irgendwie fehlt mir hier der Zusammenhang zur aufzurufenden Funktion? ?(
  • OSXDev schrieb:

    Jedoch habe ich nur Beispiele gefunden in der jeweils nur eine Funktion (laden von Fotodateien) aufgerufen wurde, welche zwar bei jedem Aufruf ein neues Ergebnis lieferte, jedoch muss ich mehrere Funktionen aufrufen die jeweils einen Datentyp (String) zu nicht definierten Zeiten zurückgeben.
    Es steht Dir doch frei, unterschiedliche asynchrone Funktionsaufrufe per addTask hinzuzufügen... Interessant wird es allerdings beim Rückgabetyp, der für alle Tasks einer Gruppe gleich sein muss - aber das scheint bei Dir ja der Fall zu sein. Vielleicht hilft dieser Artikel: Auch wenn immer URLSessions verwendet werden, liefern die Tasks unterschiedliche Ergebnisse, die mittels enum "künstlich" vereinheitlicht werden.

    Vielleicht ist ein async let ... await-Konstrukt bei Dir aber der einfachere Weg. Nachfolgend ein Beispiel, dass ich hier "geklaut" habe: Auch mit unterschiedlichen Rückgabetypen machbar und nur ein Vierzeiler:

    Quellcode

    1. func loadImages() {
    2. Task {
    3. async let firstImage = loadImage(index: 1)
    4. async let secondImage = loadImage(index: 2)
    5. async let thirdImage = loadImage(index: 3)
    6. let images = await [firstImage, secondImage, thirdImage]
    7. }
    8. }

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von MyMattes ()

  • Mit ner TaskGroup sieht es ungefähr so aus.

    Quellcode

    1. func createEncryptedEdispense(rxDaten: [RXDaten]) async -> [RXDaten] {
    2. let ergebnis = await withTaskGroup(of: RXDaten.self) { group in
    3. for rxDatum in rxDaten {
    4. group.addTask {
    5. do {
    6. let eDispense = EDispensierung(rezeptId: rxDatum.eRezeptId, eVerordnung: rxDatum.eVerordnung, quittung: rxDatum.quittungB64, eAbgabe: rxDatum.signedAbgabedaten)
    7. let xmlEncoder = XMLCoder.XMLEncoder()
    8. let eDispenseData = try xmlEncoder.encode(eDispense, withRootKey: "eDispensierung")
    9. if let eDispenseString = String(data: eDispenseData, encoding: .utf8) {
    10. XLLog(subsystem: "de.deos.fiverx", kategorie: "xmlstring", xml: eDispenseString, "Der unverschlüsselte eDispense String für Abrechnung")
    11. }
    12. let encryptionResult = try self.encrypt(message: eDispenseData)
    13. let eDispenseCrypted = EDispensierungEncrypted(rezeptId: rxDatum.eRezeptId, cipherKey: encryptionResult.cipherKey, cipherData: encryptionResult.cipherData)
    14. let eRezeptData = try xmlEncoder.encode(eDispenseCrypted, withRootKey: "eDispensierung").base64EncodedString(options: [.lineLength64Characters, .endLineWithCarriageReturn])
    15. let rzERezept = RzERezept(eRezeptId: rxDatum.eRezeptId, eRezeptData: eRezeptData)
    16. guard let ergebnis = String(data: try xmlEncoder.encode(rzERezept, withRootKey: "eRezept"), encoding: .utf8) else { throw NSError(domain: "de.deos.fiverx", code: 9, userInfo: [NSLocalizedDescriptionKey: "Kein eRezept Element String."]) }
    17. var rxDatumOut = rxDatum
    18. rxDatumOut.encryptedEdispense = try XMLElement(xmlString: ergebnis)
    19. return rxDatumOut
    20. }
    21. catch {
    22. XLError("Fehler bei createEncryptedEdispense: \(error)")
    23. var rxDatumOut = rxDatum
    24. if var fehlertexte = rxDatumOut.fehlerTexte {
    25. fehlertexte.append(error.localizedDescription)
    26. rxDatumOut.fehlerTexte = fehlertexte
    27. } else {
    28. rxDatumOut.fehlerTexte = [error.localizedDescription]
    29. }
    30. return rxDatumOut
    31. }
    32. }
    33. }
    34. var zwischenergebnis = [RXDaten]()
    35. for await result in group {
    36. zwischenergebnis.append(result)
    37. }
    38. return zwischenergebnis
    39. }
    40. return ergebnis
    41. }
    Alles anzeigen
    Man macht einfach solange irgendwelche Dinge, bis man tot ist.
    Und dann bekommen die anderen Kuchen.