Await Async TaskWhenAll

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

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von Haudruferzappeltnoch.

    Await Async TaskWhenAll

    Hallo

    Ich habe das hier: vb-paradise.de/index.php/Threa…len-Code/?action=firstNew
    verfolgt und dann eins meiner alten Tools neu geschrieben..

    Jetzt läuft es sehr viel schneller als zuvor. :thumbsup:

    Auch das Video aus dem Beitrag habe ich mir angesehen. Sehr interessant was er dort erzählt. Dazu mal eine Frage.

    Wie kann man eigentlich beeinflussen auf welcher CPU / Kern die App läuft? Nur mal Interessehalber. :)

    Hier mal Auszüge wie ich das mit dem "parallel" gemacht habe.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Enum OperationMode
    2. <Description("Es wird nur kopiert.")> CopyOnly
    3. <Description("Es wird nur gezippt.")> ZipOnly
    4. <Description("Es wird kopiert und gezippt.")> Both
    5. End Enum
    6. Module ModGlobalVars
    7. ' Global ReadOnly Variables / Propertys
    8. Public ReadOnly netCrLf As String = Environment.NewLine ' custum Carriage Return/Line Feed
    9. Public ReadOnly AppExePath As String = Application.ExecutablePath ' Path to the App.exe-File
    10. Public ReadOnly Datetoday As String = DateTime.Now.ToString("ddd dd.MM.yyyy") ' Dateformat: So 01.01.1000
    11. Public ReadOnly SaveDate As String = DateTime.Now.ToString("dd_MM_yyyy") ' Date for Directorys
    12. ' In case several SD-Cards are zipped, here with HH:mm
    13. Public ReadOnly ZipDate As String = DateTime.Now.ToString("ddMMyyyy_HH_mm") ' Date for Zip-Filenames
    14. ' Global Variables / Propertys
    15. Public Property SelectedMode As OperationMode ' The Case between Copy / Zip or Both
    16. Public Property SourceDirectory As String ' Drive/Directory from SD-Card
    17. Public Property TargetZipDrive As String ' Targetdrive for the ZipFiles
    18. Public Property TargetZipDirectory As String ' Targetdirectory for the ZipFiles
    19. Public Property TargetCopyDrive As String ' Targetdrive for the CopyFiles
    20. Public Property TargetCopyDirectory As String ' Targetdirectory for the CopyFiles
    21. Public Property SessionName As String ' The Name for the first folder
    22. Public Property Abort As Boolean ' Property for canceling the processes
    23. Friend Property CopyisReady As Boolean ' Property to unlog Controls
    24. Friend Property ZipisReady As Boolean ' Property to unlog Controls
    25. ' Method to determine the string from the ENUM
    26. Public Function GetEnumDescription(enumValue As [Enum]) As String
    27. Dim fieldInfo As Reflection.FieldInfo = enumValue.GetType().GetField(enumValue.ToString())
    28. Dim descriptionAttributes() As DescriptionAttribute =
    29. DirectCast(fieldInfo.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
    30. If descriptionAttributes.Length > 0 Then
    31. Return descriptionAttributes(0).Description
    32. Else
    33. Return enumValue.ToString()
    34. End If
    35. End Function
    36. End Module


    Auf dem Form:

    VB.NET-Quellcode

    1. #Region "RadioButton Events"
    2. Private Sub RadioButton_CheckedChanged(sender As Object, e As EventArgs) Handles RbCopyOnly.CheckedChanged, RbZippOnly.CheckedChanged, RbBooth.CheckedChanged
    3. If DirectCast(sender, RadioButton).Checked Then
    4. Dim mode As OperationMode = GetSelectedMode(sender)
    5. SelectedMode = mode
    6. LblOperationMode.Text = GetEnumDescription(mode)
    7. End If
    8. End Sub
    9. Private Function GetSelectedMode(sender As Object) As OperationMode
    10. Select Case DirectCast(sender, RadioButton).Name
    11. Case "RbCopyOnly"
    12. Return OperationMode.CopyOnly
    13. Case "RbZippOnly"
    14. Return OperationMode.ZipOnly
    15. Case "RbBooth"
    16. Return OperationMode.Both
    17. Case Else
    18. Return OperationMode.Both ' Default value
    19. End Select
    20. End Function
    21. #End Region
    22. #Region "Async Operations"
    23. Private Sub BtnStart_Click(sender As Object, e As EventArgs) Handles BtnStart.Click
    24. If ValidateInput() Then
    25. PerformSelectedOperation()
    26. End If
    27. End Sub
    28. Private Async Sub PerformSelectedOperation()
    29. LockControls()
    30. Select Case SelectedMode
    31. Case OperationMode.CopyOnly
    32. Await CopyOnlyAsync()
    33. Case OperationMode.ZipOnly
    34. Await ZippOnlyAsync()
    35. Case OperationMode.Both
    36. Await ParallelWorkAsync()
    37. End Select
    38. End Sub
    39. Private Async Function ParallelWorkAsync() As Task
    40. Dim copyTask = CopyManager.DoFileCopy()
    41. Dim zipTask = ZipManager.DoFileZip()
    42. Await Task.WhenAll(copyTask, zipTask)
    43. End Function
    44. Private Async Function CopyOnlyAsync() As Task
    45. Await CopyManager.DoFileCopy()
    46. End Function
    47. Private Async Function ZippOnlyAsync() As Task
    48. Await ZipManager.DoFileZip()
    49. End Function
    50. #End Region


    Zwei Classes:

    VB.NET-Quellcode

    1. Public Async Function DoFileZip() As Task(Of Boolean)
    2. ' Check of Source / Target Directory is valide
    3. If Not Await CheckDrives() Then
    4. .......
    5. UND DIEANDERE CLASS
    6. Public Async Function DoFileCopy() As Task(Of Boolean)
    7. ' Check of Source / Target Directory is valide
    8. If Not Await CheckDrives() Then
    9. ......

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Wie kann man eigentlich beeinflussen auf welcher CPU / Kern die App läuft? Nur mal Interessehalber.


    Das kann man nicht beeinflussen. Warum sollte man das auch können? Das System verwaltet das, und das ist gut so.

    Edit:
    Ach doch, dachte geht nur unter Linux. Aber ob NET da was an Board hat? Kannste aber selbst via WinAPI machen.

    learn.microsoft.com/en-us/wind…se-setprocessaffinitymask

    PS. Gibt was in NET
    learn.microsoft.com/en-us/dotn…sThread_ProcessorAffinity
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    @Amelie Du kannst nicht vorgeben, welcher Kern Dir zugewiesen wird.
    Du kannst aber festlegen, wie viele Kerne von Deinen Tasks verwendet werden dürfen.

    VB.NET-Quellcode

    1. ThreadPool.GetAvailableThreads(..)
    2. ThreadPool.SetMinThreads(..)
    3. ThreadPool.SetMaxThreads(..)

    learn.microsoft.com/en-us/dotn…lablethreads?view=net-8.0
    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!
    @DTF: Da geht's aber um Threads. Tasks sind ja ein anderer Schuh.
    Die Notwendigkeit einer Festlegung erkenn ich zwar nicht, aber meine Aussichten werden eh von mehreren topologischen Besonderheiten eingeschränkt.
    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 schrieb:

    Da geht's aber um Threads.


    Die Frage war ja: Wie kann man eigentlich beeinflussen auf welcher CPU / Kern die App läuft? Nur mal Interessehalber.

    Da haben wir einen Thread, den MainThread der Applikation und keinen Task.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    @VaporiZed
    Achso das mit den ENUMs habe ich in einem deiner Beiträge hier gefunden. Ursprünglich wollte ich da erst eine ListOf machen. ;)

    @DTF
    Nochmal in kürze: Task vs Thread ?(

    Hier (er)warte ich doch das, was ( oder ob ) die beiden "Task" zurückmelden :?:

    VB.NET-Quellcode

    1. Private Async Function ParallelWorkAsync() As Task
    2. Dim copyTask = CopyManager.DoFileCopy()
    3. Dim zipTask = ZipManager.DoFileZip()
    4. Await Task.WhenAll(copyTask, zipTask)
    5. End Function



    @RodFromGermany
    Werde ich mal lesen, die links.... :)
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Da kann man einiges zu sagen. Aber ich versuche mich kurz zu fassen. Beides ist für paralelle Verarbeitung gedacht. Einen Thread nimmt man eher für längere Operationen, einen Task für kleine Sachen. Task geben was zurück, Threads nicht, verhält sich ähnlich wie mit Sub und Function. Tasks kann man Canceln(CancelationToken), Threads nicht, die kann man nur bedingt(if..., while(condition){...weitermachen...}) verlassen, oder gar radikal mit dem Holzhammer abbrechen(Thread.Abort).

    Ein Thread ist immer weiter Thread und Tasks laufen im selben Thread meine ich mich zu erinnern. Aber man kann auch einen Task als LongRunning einstellen, dann wird IIRC ein Thread erzeugt. Somit sind Tasks ein wenig sparsamer, weil kein Thread erzeugt werden muss. Tasks sind also auch nur bedingt Multithreading, also falls mit longrunning Tasks ein Thread erzeugt wird.

    Was Threadsicherheit angeht haben Tasks die Nase vorn, ein Task kann von verschiedene Threads aus gleichzeitig gehandelt werden, nur Task.Dispose() ist nicht Threadsafe. Beim Threading muss man sehr aufpassen, das hast du vllt. schon mal im "UI-Thread" gemerkt(Illegaler Threadübergeifender Vorgang...) oder hier davon gelesen, aber das ist nur ein Beispiel.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    Mh, interessante Erklärungen hier, dazu dann noch meine:

    Threads werden vom Betriebssystem angefordert und gemanagt. Task sind eine Eigenimplementierung von Aufgaben in .NET und werden durch einen dahinterliegenden Worker-Pool aus Threads abgearbeitet.
    @DTF
    ​Threadübergeifender Vorgang...)

    Oh ja, da muss ich dann immer mit dem nervigen "Invoke" ran, wo ich nie genau weis, wann denn nun ein Control auf der GUI ein Invoke brauch oder eben nicht.

    ​Tasks kann man Canceln(CancelationToken), Threads nicht,

    Ah, das erklärt mir nun einiges, warum mein "Abbrechen" nicht funktionierte.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    wann denn nun ein Control auf der GUI ein Invoke brauch
    Wenn ein Befehl ein GUI-Control verändert/verändern will. Auslesen ist nicht das Problem.
    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.
    Das besagt aber effektiv nur, ob man im GUI-Thread (oder eben dem Thread, in dem das betroffene Control erstellt wurde) oder einem anderen Thread ist. Oder anders: Es sagt aus, ob man (Begin)Invoke aufrufen muss, um das GUI/Control zu ändern.

    VB.NET-Quellcode

    1. Private Async Sub BtnSaveFile_Click(sender As Object, e As EventArgs) Handles BtnSaveFile.Click
    2. Await Threading.Tasks.Task.Run(Sub() Foo)
    3. End Sub
    4. Private Sub Foo()
    5. Dim Bar = Me.Text
    6. Me.Text = "Baz"
    7. End Sub

    Zeile#6 klappt problemlos, auch wenn die Abfrage nebenläufig erfolgt. Erst die nächste Zeile crasht. Aber in der ganzen Methode gilt: InvokeRequired = True

    btw: Die deutsche Übersetzung ist der Hammer:

    Microsoft schrieb:

    […] ob der Aufrufer beim Aufruf von Methoden des Steuerelements eine Aufrufmethode aufrufen muss, da sich der Aufrufer […]

    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.

    Amelie schrieb:

    wo ich nie genau weis, wann denn nun ein Control auf der GUI ein Invoke brauch oder eben nicht.
    Dazu braucht man üblicherweise auch kein InvokeRequired.
    Als Programmierer weisst du doch, welcher Code im NebenThread läuft (und dann brauchst du Invoke oder vorzugsweise BeginInvoke).

    Es ist extrem selten, dass eine Methode mal vom MainThread, mal vom Nebenthread gerufen wird (nur da täte man .InvokeRequired brauchen).
    Hallo

    Das mit dem InvokeRequired kannte ich und habe das auch oft einfach benutzt.

    VB.NET-Quellcode

    1. If Me.InvokeRequired Then
    2. Me.Invoke(Label1.Text = text)
    3. Else
    4. Label1.Text = text
    5. End If


    ​Als Programmierer weisst du doch, welcher Code im NebenThread läuft


    Na so sicher bin ich da noch nicht, das ich dass immer genau weiß. 8| :)
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Als Programmierer weisst du doch, welcher Code im NebenThread läuft
    Na so sicher bin ich da noch nicht, das ich dass immer genau weiß.
    Da würde ich aber drauf bestehen.
    Du weisst, wie man Nebenläufigkeit umsetzt (entweder mit Async, oder oldfashioned mit Thread.Start), und hast es doch selbst hinprogrammiert.

    Ansonsten müsste ich ja denken, du kopierst dir iwelche Code-Schnippel zusammen, ohne Plan davon, was die eiglich tun.
    @Amelie: Wenn Du das nicht weißt, solltest Du Dir zumindest die Methoden markieren, die nebenläufig ablaufen. Nebenläufigkeit kann manchmal ziemlich tricky sein, von daher solltest Du diese Methoden gut im Auge behalten. Aber wenn Du weißt, dass eine Methode nebenläufig ausgeführt wird plus ein Control darin geändert wird, dann weißt Du automatisch, dass Du ein Invoke brauchst.
    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.