Task(Of T) Funktion

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Task(Of T) Funktion

    Hallo,

    wenn eine Funktion ein Task(Of T) zurückgibt, dann bedeutet das, dass die Funktion T zurückgibt aber asynchron laufen kann bzw. zur Task wird.

    Aber was genau ist das Objekt Task(Of T) ist das nur eine schreibweise um obiges zu erzielen oder unterscheidet sich das von T noch anders?

    Man kann ja zum Beispiel nicht Dim test = New Task(Of String) schreiben, sondern muss eine Funktion definieren, die zur Task wird Dim test = New Task(Of String)(AddressOf fun)
    So läuft aber Dim result = test.Result ewig. Wie kriege ich das Ergebnis da raus?

    VB.NET-Quellcode

    1. Module Module1
    2. Sub Main()
    3. Dim test = New Task(Of String)(AddressOf fun)
    4. Dim result = test.Result()
    5. End Sub
    6. Private Function fun() As String
    7. Threading.Thread.Sleep(2000)
    8. Return "Hallo"
    9. End Function
    10. End Module


    Viele Grüße
    @Haudruferzappeltnoch Glückwunsch zur 1000. :thumbup:
    Lies Dich mal in die Grundlagen ein:
    learn.microsoft.com/en-us/dotn…/async/async-return-types
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Gegenbeispiel:

    VB.NET-Quellcode

    1. Sub Main()
    2. Foo()
    3. Console.ReadLine()
    4. End Sub
    5. Private Async Sub Foo()
    6. Dim test = New Task(Of String)(AddressOf fun)
    7. test.Start()
    8. Await test
    9. Dim result = test.Result
    10. End Sub
    11. Private Function fun() As String
    12. Threading.Thread.Sleep(2000)
    13. Return "Hallo"
    14. End Function
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @VaporiZed Tatsächlich hab ich so was in der Art auch versucht, test.Start, das wars was ich nie hatte.

    So läuft mein synchrones Beispiel dann:

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim test = New Task(Of String)(AddressOf fun)
    3. test.Start()
    4. Dim result = test.Result
    5. Console.ReadLine()
    6. End Sub
    7. Private Function fun() As String
    8. Threading.Thread.Sleep(2000)
    9. Return "Hallo"
    10. End Function


    Das müsste jetzt ja äquivalent zu

    VB.NET-Quellcode

    1. Sub Main()
    2. Dim result = fun
    3. Console.ReadLine()
    4. End Sub
    5. Private Function fun() As String
    6. Threading.Thread.Sleep(2000)
    7. Return "Hallo"
    8. End Function
    sein, richtig?

    Solche Task(Of T) Funktionen denke ich funktionieren genauso, die sind als "Awaitable" gekennzeichnet, also man kann Await nutzen, aber macht es irgendeinen Sinn die ohne Await zu verwenden?

    Danke @RodFromGermany. Mir geht es mehr um das Objekt Task an sich, in den Grundlagen geht es mehr um Asynchronizität

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

    Och, es gibt bestimmt Szenarien, in denen es Sinn ergibt, sich eine Aufgabe als Variable zu merken und sie irgendwann auszuführen, ggf. eben auch synchron. Aber da kann ich nix zu beisteuern, sowas mach ich einfach nicht. Aber das heißt nix.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Die genaue VB-Syntax ist mir nicht geläufig, aber du kannst auch ein Task mit einem Delegate erstellen:

    C#-Quellcode

    1. ​async void Foo() {
    2. var myTask = new Task<string>(() => {
    3. // Berechnungen, wie auch immer
    4. return "Irgend ein String in diesem Fall";
    5. });
    6. // entweder
    7. await myTask;
    8. // oder
    9. myTask.RunSynchronously();
    10. }


    Die Variable kannst du dann auch als Rückgabewert liefern, in deine Klasse speichern oder sonst wie damit umgehen.

    Das `Task` Objekt dient als Halter für deine Aktion und bietet dem Framework die Möglichkeit, diese Aktion entweder synchron, asnychron oder unter bestimmten Umständen in einem weiteren Thread laufen zu lassen.
    Oft macht man das bei IO-lastigen Sachen, wie viele Daten von dem Festspeicher zu laden, oder Netzwerk-Traffic. Ein Download kann u.U. sehr lange dauern und in der Zeit willst du nicht, dass dein Prozess stehen bleibt.

    Das T ist einfach ein generischer Typ, den du durch jeden beliebigen Wert ersetzen kannst, den dein Task zurückliefern soll. In meinem Beispiel ist das nun ein String, aber es kann genau so gut ein sehr komplexes Objekt sein, oder sonstige Daten die deine Applikation zum Laufen benötigt.

    Wenn du `Result` oder `RunSynchronously` aufrufst, dann läuft dein Task synchron zum Rest des Hauptthreads; du erschaffst dir dadurch keinen Vorteil.
    Wenn du aber eine `async` Methode hast, kannst du mit `await` dem Compiler bzw. der Runtime sagen, dass die im Hintergrund dafür sorgen soll, dass ein Interrupt angelegt werden soll, wenn dein Task beendet wurde und die Applikation wieder dahinspringen kann.

    Ganz grobes Beispiel:
    1. Task soll 500MiB Daten herunterladen
    2. Task wird asynchron aufgerufen
    3. Runtime legt ein Interrupt an und merkt sich, wo deine Applikation nach Aufrufen des Interrupts (oder Timeouts) wieder losstarten soll
    4. Während dein Task im Hintergrund läuft (denke an ein Tab im Browser, der gerade etwas herunterlädt) kannst du in deiner Anwendung weitere Dinge erledigen
    5. Dein Task ist fertig, die Applikation springt wieder zu deinem `await` und wertet den Rest dann aus
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)
    @ErfinderDesRades Ist definitiv auch die Standardvorgehensweise!

    Problem dabei ist, dass man den Task mit `Task.Run` nicht zwischenspeichern kann - aber das ist ein esoterisches Problem.
    Ich behaupte es gibt sehr weniger Fälle, wo man das braucht; zumal die meisten Tasks einfache Actions sind, wo am Ende nichts rauspurzelt.

    Interessant wird das erst, wenn man Threading und Tasks zusammenführt, um ein hochkomplexes Biest zusammenbauen muss, um auch wirklich jeden Kern eines Servers maximal ausnutzen zu können.
    Quellcode lizensiert unter CC by SA 2.0 (Creative Commons Share-Alike)

    Meine Firma: Procyon Systems
    Meine Privatwebseite: SimonC.eu

    Bitte nicht wundern, wenn meine Aktivitäten im Forum etwas langsamer sind, ich baue gerade mein Nebengewerbe zum Vollgewerbe aus.
    Ich versuche auf euch zurückzukommen :)
    @ErfinderDesRades Das Tut habe ich selbst schon genutzt, bzw. habe ich Task schon auf diese Weise erfolgreich genutzt. Aber genau das ist der Punkt, man weiß gar nicht was man da überhaupt macht.

    Dasselbe Problem hatte ich nun mit einer Methode IrgendwasAsync, ja die kann man einfach so auch ohne Await benutzen. Daher hab ich das auch gemacht, aber nicht weil mich der synchrone Ablauf nicht stört, sondern aus Unwissenheit über Tasks. Das mal auf die Basis runterzukochen hat mir da sehr geholfen

    Haudruferzappeltnoch schrieb:

    man weiß gar nicht was man da überhaupt macht.
    8|
    Dann solange testen, bis man glaubt zu wissen, wie das Grobe abläuft, bevor man es ins eigentliche Projekt einbaut. Sonst hat man ja gar keinen Ansatz, warum was schief läuft, wenn etwas schief läuft.
    Ich muss ja zugeben, dass es bei mir inzwischen so ist, dass die Erkenntnis reift: »Oh, da läuft was schief. Ich weiß noch nicht genau, warum, aber ich komm der Sache näher.« Und dann dieses befreiende Gefühl, wenn ich dann endlich meinen in Code gegossenen Denkfehler erkenne.
    Aber Deine Aussage klingt gerade wie: »It works, but I don't know why …«
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ja das war bei z.b. Task.Run definitiv so bisher. Das was dadrin dann passiert ist natürlich was anderes. Async Await hab ich auch verstanden. Aber das steht nunmal in strenger Kooperation mit Tasks. Das ist ein kleiner Bestandteil, den nimmt man halt erstmal hin, man sieht ja man kommt gar nicht so leicht zu einer Erkenntnis an dieser Stelle.
    vielleicht hilft dieser Versuch:
    Task(Of T) ist vergleichbar einer Func(Of T)
    Beide Datentypen bestimmen ein Objekt, was eine Funktion beinhaltet, die T zurückgibt.
    Das besondere an Task(Of T) ist, dass vorgesehen ist, diese Funktion im NebenThread laufen zu lassen, und nach Ablauf der Nebenläufigkeit dort fortsetzen, wo man den Task gestartet hat.
    (ist das nicht beabsichtigt, dann soll man was anderes nehmen als Task).