Unterschied zwischen Benutzung von Async Sub und Async Task(of Type)

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von DTF.

    Neu

    Es muss halt irgendeinen Loading State geben. Daher braucht man halt ein default value, das Ladestatus impliziert oder einen generellen Ladestatus im Formular (je nach Fall). Aber ja, wohl aus dem Grund gibt es keine async properties, weil es semantisch eben keinen Sinn macht. Wenn man die unterschiedlichen Status fest definieren würde, könnte man Properties sich so verhalten lassen. Aber das trifft zu viele Annahmen. Daher wurde das denke ich (verständlicherweise) nicht gemacht.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Neu

    Hab mich jetzt für die Idee von @DTF aus Post #13 mit dem Event entschieden, funktioniert wunderbar...

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private ReadOnly Klient As New HttpClient
    2. Private CoverArtsFromPfad As New List(Of ImageSource)
    3. Public Event CoverArtFromPfadFetched()
    4. Private _CoverArtInFiles As List(Of ImageSource)
    5. <JsonIgnore>
    6. Public Property CoverArtInFiles As List(Of ImageSource)
    7. Get
    8. If _CoverArtInFiles Is Nothing Then
    9. Return FetchCoverArts()
    10. End If
    11. Return _CoverArtInFiles
    12. End Get
    13. Set(value As List(Of ImageSource))
    14. _CoverArtInFiles = value
    15. RaisePropertyChanged()
    16. End Set
    17. End Property
    18. Private Sub NewCoverArtAvailable()
    19. CoverArtInFiles = CoverArtsFromPfad
    20. End Sub
    21. Public Function FetchCoverArts() As List(Of ImageSource)
    22. If (ModelObjekt.CoverArtInFiles IsNot Nothing) Then
    23. If (ModelObjekt.CoverArtInFiles.Count > 0) Then
    24. Return ModelObjekt.CoverArtInFiles
    25. End If
    26. End If
    27. Dim uriResult As Uri = Nothing
    28. Dim result As Boolean = Uri.TryCreate(CoverArtPfad, UriKind.Absolute, uriResult) AndAlso (uriResult.Scheme = Uri.UriSchemeHttp OrElse uriResult.Scheme = Uri.UriSchemeHttps)
    29. If Not Stream Then
    30. Dim MeinTrack As ATL.Track = New ATL.Track(Dateiname)
    31. Dim GefundeneCoverArts As System.Collections.Generic.IList(Of PictureInfo) = MeinTrack.EmbeddedPictures
    32. If GefundeneCoverArts.Count > 0 Then
    33. Dim ImageListe As New List(Of ImageSource)
    34. For Each Bild In GefundeneCoverArts
    35. ImageListe.Add(BitmapToImageSource(New Bitmap(System.Drawing.Image.FromStream(New MemoryStream(Bild.PictureData)))))
    36. Next
    37. Return ImageListe
    38. Else
    39. GetCoverArtFromCoverArtPfad(CoverArtPfad, result)
    40. End If
    41. Else
    42. GetCoverArtFromCoverArtPfad(CoverArtPfad, result)
    43. End If
    44. End Function
    45. Private Async Sub GetCoverArtFromCoverArtPfad(Pfad As String, URLIsValid As Boolean)
    46. AddHandler Me.CoverArtFromPfadFetched, AddressOf NewCoverArtAvailable
    47. Dim retList As New List(Of ImageSource)
    48. If System.IO.File.Exists(Pfad) Then
    49. Try
    50. Dim memStream As MemoryStream = New MemoryStream(System.IO.File.ReadAllBytes(Pfad))
    51. retList.Add(BitmapToImageSource(New Bitmap(System.Drawing.Image.FromStream(memStream))))
    52. CoverArtsFromPfad = retList
    53. RaiseEvent CoverArtFromPfadFetched()
    54. Catch ex As Exception
    55. CoverArtsFromPfad = Nothing
    56. RaiseEvent CoverArtFromPfadFetched()
    57. End Try
    58. ElseIf URLIsValid Then
    59. Try
    60. retList.Add(BitmapToImageSource(New Bitmap(System.Drawing.Image.FromStream(Await GetCoverFromWeb(Pfad)))))
    61. CoverArtsFromPfad = retList
    62. RaiseEvent CoverArtFromPfadFetched()
    63. Catch ex As Exception
    64. CoverArtsFromPfad = Nothing
    65. RaiseEvent CoverArtFromPfadFetched()
    66. End Try
    67. Else
    68. CoverArtsFromPfad = Nothing
    69. RaiseEvent CoverArtFromPfadFetched()
    70. End If
    71. RemoveHandler Me.CoverArtFromPfadFetched, AddressOf NewCoverArtAvailable
    72. End Sub

    Neu

    Warum brauchst du jetzt noch das Event? Das ist eigentlich redundant. Du kannst doch auch in der Methode direkt die Property setzen. Im Endeffekt machst du jetzt nichts anderes, außer dass du noch den Weg über ein Event zusätzlich gehst. Dieses wird manuell im selben Thread von dir geworfen und bringt somit an der Stelle keinen Mehrwert, weil du den Handlercode direkt integrieren kannst. Du deabonnierst es schließlich auch direkt wieder. Events machen ja nur Sinn, wenn andere Instanzen etwas mitkriegen wollen oder du z.B. asynchrone Arbeit mit dem EAP abfangen willst. Innerhalb derselben Klasse hast du ja eh schon die volle Kontrolle sonst.

    Deine Property wirft ja auch PropertyChanged für die UI, d.h. da musst du ja sonst auch nichts an irgendein Event binden.

    Viele Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Trade“ ()

    Neu

    @kafffee

    So hab ich das nicht gemeint. Wie kommt denn das fertige Gericht als "Argument" vor?

    Ich hätte eine Klasse, eine Sub zum starten des Ladens(wie auch abbrechen), diese Stellt das Event zur verfügung, wenn fertig das Event feuern, aber auch eigene "EventArgs" nutzen, so kommt mit dem Event alles rein. So ist das ausreichend abgekapselt und du kannst das dann auch wieder verwenden. Was bei deinem Code nicht drin wäre. "Reusable Code" sollte man anlegen, Spaghetti vergessen, egal wie gut das schmeckt.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Neu

    Genau so würde ich es nicht machen. EAP ist veraltet. Task-basierte Operationen sind schon korrekt. Nur wurden sie hier halt mit Events vermischt, die hier eigentlich nicht nötig sind.
    Im gesamten .NET-Bereich ist TAP auch der neue Standard. Events mit eigenen EventArgs für asynchrone Operationen (Progress, Complete, ...) findet man in der aktuellen API evtl. nur noch aus Legacy-Gründen. Aber sie werden auch nicht mehr beworben. Ist halt n Standard von vor 10 Jahren.

    Viele Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Neu

    Trade schrieb:

    Ist halt n Standard von vor 10 Jahren.


    OK hast mich überzeugt. Ich bin bei NET wirklich noch auf einem älteren Stand, werde mir mal 1-2 Bücher kommen lassen. Bei Android hab ich es nicht bereut aufs neueste umzusteigen (Kotlin und auch Jetpack-Compose), sicher wirds auch Vorteile in NET haben aktuelleres zu nutzen.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Neu

    Ja, EAP hatte schon seine Daseinsberechtigung. Es war damals einfach gängig, um sowas abzubilden. Hab's selbst auch oft benutzt. Gerade weil mir das mit Async-Await usw. nicht so geläufig war. Aber TAP ist einfach eine sehr mächtige Technik und inzwischen de-facto Standard in .NET. Man kann halt mit einfacherer Methodenstruktur nun auf asynchrone Aufgaben warten und diese auch repräsentativ durch den Code durchreichen mit Tasks. Du musst halt nicht mehr Wartelogik auf mehrere Methodenausführungen verteilen.

    Als ich angefangen habe mit .NET (Framework) war es irgendwie ein Weg sich mit Thread-Joining oder ManualResetEvents zu behelfen und das hat schon irgendwie dann mal funktioniert, aber war eher so semi-toll. Davon abgesehen musste man halt an so vielen Stellen (auch mit dem EAP noch) BeginInvoke aufrufen, weil die Delegaten dann auf Handler zeigen, die nicht mehr im UI-Thread laufen und lauter solche Sachen. Da ist das schon wesentlich angenehmer nun, weil man primär die Nebenläufigkeit ja wählt, um den UI-Thread zu entblocken, aber trotzdem irgendwie auf das Ergebnis warten wollte. Gab es halt damals in .NET 3.5 und glaube sogar .NET 4 noch nicht. Erst ab 4.5 bzw. 4 mit ner NuGet-Lib. Aus Gründen der Kompatibilität hat man EAP dann oftmals verbaut. Aber das ist ja alles legacy.

    Viele Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Neu

    Das hört sich gut an, allein wenn man sich die ganze "invokerei" spart ist es das auf jeden Fall Wert zu lernen. Das erklärt auch warum man den Webclienten nicht mehr nehmen sollte, da sind die Methoden mit Async im Namen auch noch EAP. Es gab Situationen wo man APM vorziehen sollte(hab grad nicht im Kopf wann), aber ich glaube fast APM ist nicht mehr relevant?

    PS.
    EIne kleine Recherche brachte mir die Anwort sofort, APM und EAP wurden durch TAP abgelöst, ist mit der TPL mit NET 4 gekommen.
    OK, ich nutze noch "Steinzeit-Technik", das wird sich ändern.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()