WPF und Multithreading

  • WPF

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

    WPF und Multithreading

    Hallo Ihr lieben,

    ich bin mir nicht sicher ob das direkt in das WPF-Forum gehört, da ich schon immer meine Probleme mit Multithreading hatte, aber da dies mein erster Versuch in WPF ist, hab ich das mal hier aufgemacht, wenn das falsch sein sollte bitte verschieben.

    Ich bin mal über diesen Topic gestoßen Infinite-Monkey-Theorem Tool Programmieren? - Sonstige Problemstellungen - VB-Paradise 2.0 — Die große Visual–Basic– und .NET–Community (vb-paradise.de) und dachte das wäre doch mal ein gutes kleines Übungsprojekt.

    Im Vorfeld dachte ich zumindest, dass wenn ich das über Propertys regeln würde, ich in der WPF auch ohne Multithreading, einfach im ablauf eines Loops, die Ergebnisse in der UI angezeigt bekomme, wie sich nun zeigt, friert während eines Loops auch die WPF ein. Also komme ich wohl nicht um Threading herum.....

    Jedoch muss ich zugeben das es mir gänzlich am Verständniss des Threadings mangelt, man findet viele verschiedene Ansätze, direkt über Thread, über eigene Prozesse, Backgroundworker usw. aber bislang scheitere ich massiv an deren Anwendung.

    bisheriger Ansatz (definitiv nicht funktionsfähig da ja noch ohne Threading)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections.ObjectModel
    2. Imports System.Timers
    3. Imports System
    4. Imports System.ComponentModel
    5. Imports System.Windows
    6. Public Class MainViewModel
    7. Inherits BaseViewModel
    8. Public Shared ReadOnly Instance As New MainViewModel
    9. Dim rnd As New Random
    10. Dim rndWord As New Text.StringBuilder
    11. Dim Runtimer As New Stopwatch
    12. Private _targetWord As String = String.Empty
    13. Public Property TargetWord() As String
    14. Get
    15. Return _targetWord
    16. End Get
    17. Set(ByVal value As String)
    18. ChangePropIfDifferent(value, _targetWord)
    19. End Set
    20. End Property
    21. Private _runtime As TimeSpan = TimeSpan.Zero
    22. Public Property Runtime() As TimeSpan
    23. Get
    24. Return _runtime
    25. End Get
    26. Set(ByVal value As TimeSpan)
    27. ChangePropIfDifferent(value, _runtime)
    28. End Set
    29. End Property
    30. Private _results As ObservableCollection(Of String) = New ObservableCollection(Of String)
    31. Public Property Results() As ObservableCollection(Of String)
    32. Get
    33. Return _results
    34. End Get
    35. Set(ByVal value As ObservableCollection(Of String))
    36. ChangePropIfDifferent(value, _results)
    37. End Set
    38. End Property
    39. Public ReadOnly Property StartMonkeysCommand As New RelayCommand(AddressOf StartMonkeysCommand_Execute, Function(o) TargetWord IsNot String.Empty)
    40. Private Sub StartMonkeysCommand_Execute(obj As Object)
    41. MonkeysAtWork()
    42. End Sub
    43. Private Sub MonkeysAtWork()
    44. Runtimer.Reset()
    45. Do Until Results.Contains(TargetWord)
    46. For i As Integer = 0 To TargetWord.Length - 1
    47. rndWord.Append(Chr(rnd.Next(65, 90)))
    48. Next
    49. Results.Add(rndWord.ToString)
    50. Runtime = Runtimer.Elapsed
    51. rndWord.Clear()
    52. Loop
    53. End Sub
    54. End Class



    Ich müsste also einen Weg finden um:

    VB.NET-Quellcode

    1. Do Until Results.Contains(TargetWord)
    2. For i As Integer = 0 To TargetWord.Length - 1
    3. rndWord.Append(Chr(rnd.Next(65, 90)))
    4. Next
    5. Results.Add(rndWord.ToString)
    6. Runtime = Runtimer.Elapsed
    7. rndWord.Clear()
    8. Loop


    Diese Sub in nach Möglichkeit so vielen Threads auszuführen wie Kerne da Sind, aber ich komme nichtmal auf einen guten Ansatz wie ich das versuchen könnte, evtl. kann mir von euch ja jemand ein kleines Beispiel posten, wie Ihr in so einem Fall auf Threading zurückgreift ? Was soll cih wählen, Backgroundworker oder Threads direkt ? Und ich stoße hierbei auch immer wieder auf so genanntes Invoken, was sich mir auch noch nicht erschließt. Bitte nicht falsch verstehen, ich möchte keinen vorgekauten Code, aber ein gutes Beispiel und ein paar Ansätze wären echt eine große Hilfe


    Vielen dank schonmal =)


    Nachtrag: Ich habs zumindest schonmal soweit hinbekommen, das ich einen Thread zum laufen bekomme,

    Spoiler anzeigen

    VB.NET-Quellcode

    1. ​Imports System.Collections.ObjectModel
    2. Imports System.Timers
    3. Imports System
    4. Imports System.ComponentModel
    5. Imports System.Windows
    6. Public Class MainViewModel
    7. Inherits BaseViewModel
    8. Public Shared ReadOnly Instance As New MainViewModel
    9. Dim Runtimer As New Stopwatch
    10. #Region "ThreadSafeStuff"
    11. Delegate Sub Update_UI(ByVal FoundString As String)
    12. Public Sub Update_UISub(ByVal FoundString As String)
    13. Results.Add(FoundString)
    14. Runtime = Runtimer.Elapsed
    15. End Sub
    16. #End Region
    17. Private _targetWord As String = String.Empty
    18. Public Property TargetWord() As String
    19. Get
    20. Return _targetWord
    21. End Get
    22. Set(ByVal value As String)
    23. ChangePropIfDifferent(value, _targetWord)
    24. End Set
    25. End Property
    26. Private _runtime As TimeSpan = TimeSpan.Zero
    27. Public Property Runtime() As TimeSpan
    28. Get
    29. Return _runtime
    30. End Get
    31. Set(ByVal value As TimeSpan)
    32. ChangePropIfDifferent(value, _runtime)
    33. End Set
    34. End Property
    35. Private _results As ObservableCollection(Of String) = New ObservableCollection(Of String)
    36. Public Property Results() As ObservableCollection(Of String)
    37. Get
    38. Return _results
    39. End Get
    40. Set(ByVal value As ObservableCollection(Of String))
    41. ChangePropIfDifferent(value, _results)
    42. End Set
    43. End Property
    44. Public ReadOnly Property StartMonkeysCommand As New RelayCommand(AddressOf StartMonkeysCommand_Execute, Function(o) TargetWord IsNot String.Empty)
    45. Private Sub StartMonkeysCommand_Execute(obj As Object)
    46. Runtimer.Reset()
    47. Dim neuerthread As System.Threading.Thread
    48. neuerthread = New System.Threading.Thread(AddressOf MonkeysAtWork)
    49. neuerthread.Start(TargetWord) 'Vorgang starten
    50. Runtimer.Start()
    51. End Sub
    52. Private Sub MonkeysAtWork(TargetWord As String)
    53. Dim Upd As New Update_UI(AddressOf Update_UISub)
    54. Dim Result As String = String.Empty
    55. Dim rnd As New Random
    56. Dim rndWord As New Text.StringBuilder
    57. Do Until Result = TargetWord
    58. Result = String.Empty
    59. For i As Integer = 0 To TargetWord.Length - 1
    60. rndWord.Append(Chr(rnd.Next(65, 90)))
    61. Next
    62. Result = rndWord.ToString
    63. Application.Current.Dispatcher.Invoke(Upd, Result)
    64. rndWord.Clear()
    65. Loop
    66. End Sub
    67. End Class


    allerdings friert das Programm ein, wenn ich auf diese Weise versuche, mehrere Threads davon zu starten, aber es muss doch irgendwie möglich sein, meinen Prozessor damit auch wirklich auf Anschlag auszulasten, also mehrere Threads zeitgleich an so einer Aufgabe arbeiten zu lassen, oder nicht ?
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    Grundsätzlich ist Threading doch nicht weiter kompliziert:
    1) Eine Aufgabe wird in einen NebenThread verlegt, "abgefeuert" und "vergessen" - d.h. der MainThread kann ungestört fortfahren.
    2) ist die Aufgabe erledigt, meldet der NebenThread sich zurück, und die Ergebnisse werden (im MainThread) eingepflegt.

    Das lässt sich ideal mit dem Async/Await-Pattern abfackeln: codeproject.com/Articles/10296…ithout-any-additional-Lin
    Bereits der erste Abschnitt des Tuts passt ist wie geschaffen für dein Anliegen und erstmal ausreichend.

    Du hast da noch einen Zusatz-Wunsch: Du willst bestimmen, dass mehrere Kernel beaufschlagt werden.
    Das ist ein zweiter Entwicklungs-Schritt - innerhalb des NebenThreads nun Parallel.For korrekt einsetzen.
    Ich weiss nicht, ob das Monkey-Problem für Parallel.For zugänglich ist, afaik benötigt Parallel.For eine Input-Menge.
    D.h. zB ein Permutations-Algorithmus, bei dem sich aus jedem Ergebnis das nächste ableitet, ist nicht parallelisierbar, weil es gibt zu jedem Zeitpunkt immer nur einen Input.
    Und es ist auch nicht ganz trivial, zB 4 Inputs zu schaffen, weil dann ist u.U. möglich, dass die Ergebnis-Mengen, wenn man sie später zusammenführt, haufenweise Dubletten enthalten.
    hm, also gesetzt dem Fall ich hab das richtig umgesetzt, hilft es leider nicht, da ich per AddressOf, so keinen Parameter mit übergeben kann <---- ok, das ist erledigt.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections.ObjectModel
    2. Imports System.Timers
    3. Imports System
    4. Imports System.ComponentModel
    5. Imports System.Windows
    6. Imports System.Threading
    7. Public Class MainViewModel
    8. Inherits BaseViewModel
    9. Public Shared ReadOnly Instance As New MainViewModel
    10. Dim Runtimer As New Stopwatch
    11. Private _targetWord As String = String.Empty
    12. Public Property TargetWord() As String
    13. Get
    14. Return _targetWord
    15. End Get
    16. Set(ByVal value As String)
    17. ChangePropIfDifferent(value, _targetWord)
    18. End Set
    19. End Property
    20. Private _runtime As TimeSpan = TimeSpan.Zero
    21. Public Property Runtime() As TimeSpan
    22. Get
    23. Return _runtime
    24. End Get
    25. Set(ByVal value As TimeSpan)
    26. ChangePropIfDifferent(value, _runtime)
    27. End Set
    28. End Property
    29. Private _results As ObservableCollection(Of String) = New ObservableCollection(Of String)
    30. Public Property Results() As ObservableCollection(Of String)
    31. Get
    32. Return _results
    33. End Get
    34. Set(ByVal value As ObservableCollection(Of String))
    35. ChangePropIfDifferent(value, _results)
    36. End Set
    37. End Property
    38. Private WithEvents _Progress As New Progress(Of List(Of String))
    39. Private Sub Progress_ProgressChanged(sender As Object, e As List(Of String)) Handles _Progress.ProgressChanged
    40. For Each s As String In e
    41. Results.Add(s)
    42. Next
    43. End Sub
    44. Public ReadOnly Property StartMonkeysCommand As New RelayCommand(AddressOf StartMonkeysCommand_Execute, Function(o) TargetWord IsNot String.Empty)
    45. Private Async Sub StartMonkeysCommand_Execute(obj As Object)
    46. Runtimer.Reset()
    47. Runtimer.Start()
    48. Await Task.Run(Sub() MonkeysAtWork(TargetWord))
    49. End Sub
    50. Private Sub MonkeysAtWork(TargetWord As String)
    51. Dim prgs As IProgress(Of List(Of String)) = _Progress
    52. Dim Result As List(Of String) = New List(Of String)
    53. Dim rnd As New Random
    54. Dim rndWord As New Text.StringBuilder
    55. Do Until Result.Contains(TargetWord)
    56. For i As Integer = 0 To TargetWord.Length - 1
    57. rndWord.Append(Chr(rnd.Next(65, 90)))
    58. Next
    59. Result.Add(rndWord.ToString)
    60. If Result.Count > 10000 Then
    61. prgs.Report(Result)
    62. Result.Clear()
    63. End If
    64. rndWord.Clear()
    65. Loop
    66. End Sub


    Ich denke ich habs zumindest soweit das es funktioniert, nur krieg ichs nicht hin das ich auch Rückgabewerte bekomme....

    er meckert immer hier:

    VB.NET-Quellcode

    1. Private Sub Progress_ProgressChanged(sender As Object, e As List(Of String)) Handles _Progress.ProgressChanged
    2. For Each s As String In e
    3. Results.Add(s)
    4. Next
    5. End Sub

    "Die Sammlung wurde geändert. Der Enumerationsvorgang kann möglicherweise nicht ausgeführt werden."
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    Da hab ich mich vermutlich falsch ausgedrückt,

    Im Prinzip würde ich anstreben: Ich Starte die Äffchen, möglichst viele Zeitgleich, und irgendwie muss ich ja in der UI anzeigen, was jedes dieser Äffchen tut, also im Endeffekt die jeweiligen generierten Strings irgendwie aus diesen Threads in der UI anzeigen, sobald eines der Äffchen das TargetWord gefunden hat, sollen alle anderen auch aufhören, nur irgendwie krieg ich ja noch nichtmal die aktuellen Daten aus den Threads in die UI, geschweige denn das ich bereits wüsste wie ich die Threads dann schließen könnte sobald einer fertig ist.

    Nachtrag: Habe jetzt alles nochmal etwas überarbeitet, und denke mal das ich deinen Async-Vorschlag korrekt eingebaut habe, nur krieg ich auch auf diese Weise nur einen einzelnen Thread zum laufen...

    Spoiler anzeigen

    VB.NET-Quellcode

    1. ​Imports System.Collections.ObjectModel
    2. Imports System.Timers
    3. Imports System
    4. Imports System.ComponentModel
    5. Imports System.Windows
    6. Imports System.Threading
    7. Public Class MainViewModel
    8. Inherits BaseViewModel
    9. Public Shared ReadOnly Instance As New MainViewModel
    10. Dim Runtimer As New Stopwatch
    11. Private _targetWord As String = String.Empty
    12. Public Property TargetWord() As String
    13. Get
    14. Return _targetWord
    15. End Get
    16. Set(ByVal value As String)
    17. ChangePropIfDifferent(value, _targetWord)
    18. End Set
    19. End Property
    20. Private _runtime As TimeSpan = TimeSpan.Zero
    21. Public Property Runtime() As TimeSpan
    22. Get
    23. Return _runtime
    24. End Get
    25. Set(ByVal value As TimeSpan)
    26. ChangePropIfDifferent(value, _runtime)
    27. End Set
    28. End Property
    29. Private _results As ObservableCollection(Of String) = New ObservableCollection(Of String)
    30. Public Property Results() As ObservableCollection(Of String)
    31. Get
    32. Return _results
    33. End Get
    34. Set(ByVal value As ObservableCollection(Of String))
    35. ChangePropIfDifferent(value, _results)
    36. End Set
    37. End Property
    38. Public ReadOnly Property StartMonkeysCommand As New RelayCommand(AddressOf StartMonkeysCommand_Execute, Function(o) TargetWord IsNot String.Empty)
    39. Private Sub StartMonkeysCommand_Execute(obj As Object)
    40. Runtimer.Reset()
    41. Runtimer.Start()
    42. SendMonkeysToWork(TargetWord, Results)
    43. End Sub
    44. Private Async Sub SendMonkeysToWork(TargetWord As String, ByVal Results As ObservableCollection(Of String))
    45. Do Until Results.Contains(TargetWord)
    46. Dim Stringlist = Await Task.Run(Function() MonkeyAtWork(TargetWord))
    47. For Each s As String In Stringlist
    48. Results.Add(s)
    49. Next
    50. Runtime = Runtimer.Elapsed
    51. Loop
    52. End Sub
    53. Private Function MonkeyAtWork(TargetWord As String) As List(Of String)
    54. Dim Result As List(Of String) = New List(Of String)
    55. Dim rnd As New Random
    56. Dim rndWord As New Text.StringBuilder
    57. For I As Integer = 1 To 1000
    58. For ii As Integer = 0 To TargetWord.Length - 1
    59. rndWord.Append(Chr(rnd.Next(65, 90)))
    60. Next
    61. Result.Add(rndWord.ToString)
    62. rndWord.Clear()
    63. Next
    64. Return Result
    65. End Function
    66. End Class

    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    Jo, so ist wie ich gedacht hab.
    Und es zeigt sich, dass das wohl nicht sinnvoll ist als nebenläufige Aufgabe, weil 1000 Worte zu generieren ist vmtl. nur ein Zucken - oder?
    Diese Monkey-Arbeit ist wohl überhaupt kein gutes Studien-Objekt für Threading, weil die wird ja nie fertig.

    Naja - vielleicht doch.
    Weil Nun kannst du Experimente machen, wie lang das Wort sein muss, dass es in einer sinnvollen Zeit gefunden wird. Die Zeiten werden stark schwanken, aber länger als 10s wirds wohl kein Spass machen.
    Und wenn du das erreicht hast: einen "Versuchs-Aufbau", der durchschnittlich 5s läuft - dann kannste das Verfahren mit Parallel.For auf mehrere Kernels verteilen.

    Deine Zeitmessung sollte übrigens direkt nach dem Await-Call erfolgen - dass du das Ergebnis erst noch in eine OC umfüllst, wo auch noch dran gebunden ist - das kann die Messung evtl. sehr verfälschen.



    Nee - isses wohl aber auch nicht.
    Du schickst ihn ja immer wieder ins Await - bis das Targetwort gefunden wurde.
    Async-Pattern ist, dass er einmal in die Nebenläufigkeit geht, und erst returnt, wenner fertig ist.

    ErfinderDesRades schrieb:


    Und es zeigt sich, dass das wohl nicht sinnvoll ist als nebenläufige Aufgabe, weil 1000 Worte zu generieren ist vmtl. nur ein Zucken - oder?

    Nun kannst du Experimente machen, wie lang das Wort sein muss, dass es in einer sinnvollen Zeit gefunden wird. Die Zeiten werden stark schwanken, aber länger als 10s wirds wohl kein Spass machen.
    Und wenn du das erreicht hast: einen "Versuchs-Aufbau", der durchschnittlich 5s läuft - dann kannste das Verfahren mit Parallel.For auf mehrere Kernels verteilen.

    Deine Zeitmessung sollte übrigens direkt nach dem Await-Call erfolgen - dass du das Ergebnis erst noch in eine OC umfüllst, wo auch noch dran gebunden ist - das kann die Messung evtl. sehr verfälschen.



    Nee - isses wohl aber auch nicht.
    Du schickst ihn ja immer wieder ins Await - bis das Targetwort gefunden wurde.
    Async-Pattern ist, dass er einmal in die Nebenläufigkeit geht, und erst returnt, wenner fertig ist.



    Ja die 1000 Strings gehen ansich ziemlich fix, aktuell versuche ich es mit dem Wörtchen "Hallo" da sitzt der nun aber schon gut 20 Minuten dran ^^


    Der Grundlegende Gedanke, weshalb ich diesen Ansatz gewählt habe ist der, das ich so immer wieder Rückgabewerte bekomme, Ohne das ich irgendwelche Probleme damit habe an die Daten heranzukommen, und nur wenn nicht das Gewünschte Wort enthalten ist, wird erneut aufgerufen, du sagst also der Ansatz macht so keinen Sinn ?
    Und verzeih mir das ich nachfragen muss, was ist denn bitte eine OC ? Zum Thema ParralelFor, das hab ich die letzten 2 Stunden versucht, aber ich finde keine für mich begreiflichen Tutorials dazu und verstehe 0 damit umzugehen, leider...
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    OC: ObservableCollection - ich hab eine Lese-Schreibschwäche bei langen Wörtern.

    asusdk schrieb:

    Ja die 1000 Strings gehen ansich ziemlich fix, aktuell versuche ich es mit dem Wörtchen "Hallo" da sitzt der nun aber schon gut 20 Minuten dran
    Ich nehme an, 19,99 Minuten davon verbringt er damit, die Strings in die OC einzufügen, und per DataBinding im GUI drauf zu reagieren.
    Es scheint mir keine gute Idee, sämtliche ausprobierten Zufalls-Worte anzeigen zu wollen. Das wird sich niemand durchlesen wollen, ausser vlt. Chuck Norris.
    Hehe, ja Chuck Norris müsste die Listbox aber nur angucken und aus Angst würde die ihm freiwillig verraten was er wissen will :P
    Ich hab mir was in die Richtung gedacht und hab daher davon abgesehen die tatsächlichen Wörter anzeigen zu wollen, und bin auf einen schlichten Word-Counter gewechselt. Das Wort SONGUKO war nach etwa 9 Milliarden Wörtern endlich gefunden, benötigte aber auch so noch gut 20 Minuten

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class MainViewModel
    2. Inherits BaseViewModel
    3. Public Shared ReadOnly Instance As New MainViewModel
    4. Dim Runtimer As New Stopwatch
    5. Private _targetWord As String = String.Empty
    6. Public Property TargetWord() As String
    7. Get
    8. Return _targetWord
    9. End Get
    10. Set(ByVal value As String)
    11. ChangePropIfDifferent(value, _targetWord)
    12. End Set
    13. End Property
    14. Private _runtime As TimeSpan = TimeSpan.Zero
    15. Public Property Runtime() As TimeSpan
    16. Get
    17. Return _runtime
    18. End Get
    19. Set(ByVal value As TimeSpan)
    20. ChangePropIfDifferent(value, _runtime)
    21. End Set
    22. End Property
    23. Private _generatedWords As Long = 0
    24. Public Property GeneratedWords() As Long
    25. Get
    26. Return _generatedWords
    27. End Get
    28. Set(ByVal value As Long)
    29. ChangePropIfDifferent(value, _generatedWords)
    30. End Set
    31. End Property
    32. Public ReadOnly Property StartMonkeysCommand As New RelayCommand(AddressOf StartMonkeysCommand_Execute, Function(o) TargetWord IsNot String.Empty)
    33. Private Sub StartMonkeysCommand_Execute(obj As Object)
    34. Runtimer.Reset()
    35. Runtimer.Start()
    36. GeneratedWords = 0
    37. SendMonkeysToWork(TargetWord.ToUpper)
    38. End Sub
    39. Private Async Sub SendMonkeysToWork(TargetWord As String)
    40. Do
    41. Dim Stringcount = Await Task.Run(Function() MonkeyAtWork(TargetWord))
    42. GeneratedWords += Stringcount
    43. Runtime = Runtimer.Elapsed
    44. If Stringcount < 100000 Then Exit Do
    45. Loop
    46. End Sub
    47. Private Function MonkeyAtWork(TargetWord As String) As Long
    48. Dim Result As Long = 0
    49. For I As Integer = 1 To 100000
    50. Dim ActualWord = NewRandomString(TargetWord.Length)
    51. Result += 1
    52. If ActualWord = TargetWord Then
    53. If Result >= 100000 Then Result = 99999
    54. Exit For
    55. End If
    56. Next
    57. Return Result
    58. End Function
    59. Dim rnd As New System.Random
    60. Private Function NewRandomString(ByVal length As Integer) As String
    61. If length <= 0 Then Return ""
    62. Dim CharSet As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    63. Dim GenRandomStr As New Text.StringBuilder
    64. Dim RandomBytes(length - 1) As Byte
    65. rnd.NextBytes(RandomBytes)
    66. For i As Integer = 0 To length - 1
    67. GenRandomStr.Append(CharSet(RandomBytes(i) Mod CharSet.Length))
    68. Next
    69. Return GenRandomStr.ToString
    70. End Function
    71. End Class


    Jetzt müsste ich noch rauskiregen wie ich das mit Parralel.For zum laufen kriege oder ?
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    erstmal ein paar Vereinfachungen:

    VB.NET-Quellcode

    1. Private Function MonkeyAtWork(TargetWord As String) As Long
    2. For i As Long = 1 To Long.MaxValue
    3. If NewRandomString(TargetWord.Length) = TargetWord Then Return i
    4. Next
    5. Return -1L
    6. End Function
    7. Dim rnd As New System.Random
    8. Private Function NewRandomString(length As Integer) As String
    9. Const CharSet As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    10. Dim chars = Enumerable.Range(0, length).Select(Function(x) CharSet(rnd.Next(0, 25)))
    11. Return New String(chars.ToArray)
    12. End Function




    Jetzt habich mir Parallel.For nochmal angeguckt - ist wohl der falsche Dampfer.
    Weil das will alle Threads zuende bringen.

    Du aber willst beenden, sobald der erste fertig ist.
    Dieses Anliegen ist durch Task.WaitAny() abgebildet.

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

    hm also mit der Stopwatch gestestet, ist die neue RandomStringmethode um einiges Langsamer als die alte, ich hatte das extra über Bytes gelöst, da lt.: vb.net - Generate Random String is very slow - Stack Overflow das dann knapp 34% schneller ist, und du meintest ja vorhin ich soll das so stark beschleunigen wie möglich.
    die neue MonkeyAtWork Methode verstehe ich absolut gar nicht, also von der Syntax her, und die Updatet auch scheinbar deutlich seltener, kannst du mir die evtl. etwas genauer erläutern ?

    Lg und danke dir
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    naja, meine MonkeyWorkAt returnt, wenn sie das Ergebnis hat - nicht vorher.
    Deine returnt scheints auch nach 100000 Iterationen - ohne Ergebnis.

    kann ich natürlich auch machen:

    VB.NET-Quellcode

    1. Private Function MonkeyAtWork(TargetWord As String) As Long
    2. For i As Long = 1 To 99999
    3. If NewRandomString(TargetWord.Length) = TargetWord Then Return i
    4. Next
    5. Return 100000
    6. End Function
    Findich aber kein gut Design, weil die Methode tut einfach nicht, was man intuitiv von ihr erwarten würde.
    Allgemein üblich ist, dass eine Suche mit numerischem Ergebnis -1 zurückgibt, wenn sie nix findet.



    Fürs Paralellisieren ist auch wichtig, dass die Methode nicht ohne Ergebnis verfrüht returnt.
    Also würde ich doch meine erste Version empfehlen.

    Zu dem anderen: Überrascht mich, dass das langsamer ist - dann lass halt so.

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

    Das ergibt durchaus Sinn, da bin ich ganz bei dir und so oder so, danke ich dir wirklich vielmals dafür, das du mir so oft unter die Arme greifst, obwohl bei mir noch soviel Grundwissen fehlt! Ich bin mir auch nur deswegen unsicher damit, da die UI so ja nicht wirklich anzeigt das etwas getan wird, ohne das hin und wieder der WortCount oder der Timer etwas anderes anzeigen, so bleibt die UI zwar responsive aber indiziert dennoch nicht das Programm an sich derzeit etwas tut. Vielleicht hab ich auch einen grundlegend falschen Ansatz gewählt, ich werd das alles nochmal von Grundauf neu durchdenken müssen.

    LG =)
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    asusdk schrieb:

    Vielleicht hab ich auch einen grundlegend falschen Ansatz gewählt
    Ansatz für was? - was willst du erreichen?
    Vermutlich kann mans durchaus mit Async/Await und Task lösen, aber man muss definieren, was man braucht.
    Und dann schrittweise aufbauen.
    Habich im verlinkten Tut eiglich vorexerziert, und benenne da auch die verschiedenen Anforderungen, die man an GUI-Nebenläufigkeit haben kann:
    • GUI entblocken, aber Rückgabewert erhalten
    • Nebenläufigkeit absichern gegen mehrfaches auslösen
    • Prozess-Feedback - also was der Thread grad macht
    • canceln
    • Fehler-Behandlung
    Jo, das muss man trennen, und zB nicht von "Rückgabewert" sprechen, wenn man "Prozess-Feedback" meint.
    Ausserdem hast du noch ein sechstes erwähnt: Die Last verteilen auf mehrere Kerne.