Problem mit dem .add in Parallel.ForEach

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

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Dani=mc^2.

    Problem mit dem .add in Parallel.ForEach

    Hallo zusammen

    Ich sitze gerade seit min 12 Stunden daran so optional und schnell wie mögliche alle schwarzen Pixel aus diesem Bild zu Filtern und in eine List(Of Point) zu stecken.
    Problem ist ich bekomme immer dies Fehlermeldung und kann nichts damit anfangen direkt, das bedeutet ich weiß nicht wie ich diesen Fehler behebe


    Spoiler anzeigen

    VB.NET-Quellcode

    1. #Region "Pixel zeichen"
    2. Private Async Sub pixel_erstellen()
    3. Await Task.Run(Sub()
    4. Dim bmp As New Bitmap(300, 300)
    5. For x As Integer = 0 To bmp.Width - 1
    6. For y As Integer = 0 To bmp.Height - 1
    7. Dim i As Integer = R.Next(10) 'pixel dichte
    8. If i = 1 Then bmp.SetPixel(x, y, Color.Black)
    9. 'bmp.SetPixel(R.Next(0, 300), R.Next(0, 300), Color.Black)
    10. Next
    11. Next
    12. PictureBox1.Image = bmp
    13. End Sub)
    14. End Sub
    15. #End Region
    16. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    17. AllezuListe()
    18. End Sub
    19. Private Iterator Function auslesen() As IEnumerable(Of Point)
    20. Dim Bild As Bitmap = New Bitmap(PictureBox1.Image)
    21. For x As Integer = 0 To Bild.Width - 1
    22. For y As Integer = 0 To Bild.Height - 1
    23. Dim k As Integer = Bild.GetPixel(x, y).ToArgb
    24. If Color.Black.ToArgb = k Then Yield New Point(x, y)
    25. Next
    26. Next
    27. End Function 'Gibt die Koordinaten der schwarzen Punkte durch
    28. '(Iteration) , d.h. nacheinander
    29. Private Function AllezuListe() As List(Of Point)
    30. Dim PP As New List(Of Point)
    31. '<-------
    32. Parallel.ForEach(auslesen, Async Sub(c) Await Task.Run(Sub() PP.Add(c))) ' Fehler bei PP.Add(c)
    33. MessageBox.Show(String.Concat("Inhalt: ", PP.Count))
    34. Return PP '{(x,y),(x,y)...}
    35. '---------->
    36. End Function
    Du weißt schon, dass dass dir 90% der Performance durch deine sinnlosen Tasks drauf gehen? Überall einen Task hinklatschen lässt das auch nicht schneller werden. Weshalb machst du in einer Parallel-ForEach Schleife nochmal Task.Run? Das ist komplett falsch und kontraproduktiv.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    also ich hab jetzt mehrer Möglichkeiten ausprobiert aber was ich mich frage warum macht das Parallel.ForEach nicht was die normal Schleife macht?
    Wegen dem Yield beu Auslesen?

    eine Parallel.ForEach ist doch genau das gleiche wie ein For Each oder nicht ?


    Spoiler anzeigen

    Visual Basic-Quellcode

    1. '<-------
    2. '<--Fehler 1 -->
    3. 'Parallel.ForEach(auslesen, Async Sub(c) Await Task.Run(Sub() PP.Add(c))) 'PP.Add(c)
    4. '<--End Fehler-->
    5. '<--Fehler 2 -->
    6. 'Parallel.ForEach(auslesen, Sub(c) PP.Add(c)) 'PP.Add(c)
    7. '<--End Fehler-->
    8. '<--so geht es -->
    9. For Each c As Point In auslesen()
    10. PP.Add(c)
    11. Next
    12. '<-- end so geht es -->

    Dani=mc^2 schrieb:

    ist doch genau das gleiche wie ein For Each
    Nein, Foreach führt alle Iterationen nacheinander aus, Parallel.ForEach läuft parallel ab (pst. deswegen ist die Funktion in der Parallel-Klasse, aber nicht weitersagen). Nur die List(Of T) kann mit parallelen Add-Aufrufen nicht umgehen, die kommen sich dann gegenseitig in die Quere und verursachen einen Fehler. Du könntest mit Lock arbeiten aber das würde den Geschwindigkeitszuwachs durch Parallelisierung wieder zunichte machen, klüger wäre es in verschiedene Listen zu schreiben und diese dann später zusammenzufügen.

    Artentus schrieb:

    Lock


    Wie mit Lock

    Also es mal so zusagen, wir reden hier ein von rund 1 Mil. Werten( Die werden gerade noch von Pixeln dagestellt) die es später sind.

    Also ich hab das jetzt erstmal so umgesetzt aber was mir nicht gefällt ist das mein Form einfiert, also hängt sich kurzzeitig auf

    Das ist aber Jetzt die ganze Such Methode nach den Pixeln c:

    Und es geht immer noch nocht

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. ZuL()
    3. End Sub
    4. Public Structure PointToPoint
    5. Public Punktwert As WP
    6. Public x, y, xI, yI, xII, yII As Integer
    7. Public Tan_winkel, Abstand As Double
    8. Public Class Brechnung
    9. Public Shared Function Vergleich(Wert As Integer, WertI As Integer) As Integer
    10. If Wert < WertI Then Return WertI - Wert
    11. Return Wert - WertI
    12. End Function
    13. Public Shared Function Seite_c(a As Integer, b As Integer) As Double
    14. Return Math.Sqrt((a ^ 2) + (b ^ 2))
    15. End Function
    16. End Class
    17. Public Sub New(Pointe As WP)
    18. Punktwert = Pointe
    19. xI = Punktwert.PunktI.X
    20. yI = Punktwert.PunktI.Y
    21. xII = Punktwert.PunktII.X
    22. xII = Punktwert.PunktII.Y
    23. x = Brechnung.Vergleich(xI, xII)
    24. y = Brechnung.Vergleich(yI, yII)
    25. Tan_winkel = y / x
    26. Abstand = Brechnung.Seite_c(x, y)
    27. End Sub
    28. End Structure
    29. Public Structure WP
    30. Public PunktI, PunktII As Point
    31. Public Sub New(PI As Point, PII As Point)
    32. PunktI = PI
    33. PunktII = PII
    34. End Sub
    35. End Structure
    36. #Region "Pixel zeichen"
    37. Public setii As Integer = 0
    38. Private Async Sub pixel_erstellen()
    39. Await Task.Run(Sub()
    40. Dim bmp As New Bitmap(300, 300)
    41. For x As Integer = 0 To bmp.Width - 1
    42. For y As Integer = 0 To bmp.Height - 1
    43. Dim i As Integer = R.Next(10) 'pixel dichte
    44. If i = 1 Then
    45. bmp.SetPixel(x, y, Color.Black)
    46. setii += 1
    47. End If
    48. 'bmp.SetPixel(R.Next(0, 300), R.Next(0, 300), Color.Black)
    49. Next
    50. Next
    51. PictureBox1.Image = bmp
    52. End Sub)
    53. End Sub
    54. #End Region
    55. Private Iterator Function auslesen() As IEnumerable(Of Point)
    56. Dim Bild As Bitmap = New Bitmap(PictureBox1.Image)
    57. For x As Integer = 0 To Bild.Width - 1
    58. For y As Integer = 0 To Bild.Height - 1
    59. Dim k As Integer = Bild.GetPixel(x, y).ToArgb
    60. If Color.Black.ToArgb = k Then Yield New Point(x, y)
    61. Next
    62. Next
    63. End Function 'Gibt die Koordinaten der schwarzen Punkte durch
    64. '(Iteration) , d.h. nacheinander
    65. Private Function AllezuListe() As List(Of Point)
    66. Dim PP As New List(Of Point)
    67. '<-------
    68. '<--Fehler 1 -->
    69. 'Parallel.ForEach(auslesen, Async Sub(c) Await Task.Run(Sub() PP.Add(c))) 'PP.Add(c)
    70. '<--End Fehler-->
    71. '<--Fehler 2 -->
    72. 'Parallel.ForEach(auslesen, Sub(c) PP.Add(c)) 'PP.Add(c)
    73. '<--End Fehler-->
    74. '<--so geht es -->
    75. For Each c As Point In auslesen()
    76. PP.Add(c)
    77. Next
    78. '<-- end so geht es -->
    79. 'PP.Add(c)
    80. 'MessageBox.Show(String.Concat("Inhalt: ", PP.Count, " Mussen es sein: ", setii))
    81. Return PP '{(x,y),(x,y)...}
    82. '---------->
    83. End Function
    84. Private Iterator Function zusammenfügen() As IEnumerable(Of WP)
    85. Dim ii As New List(Of WP)
    86. Dim P_Table As List(Of Point) = AllezuListe()
    87. For Each c As Point In P_Table
    88. For Each f As Point In P_Table
    89. Yield New WP(c, f)
    90. Next
    91. Next
    92. ' MessageBox.Show(String.Concat("Inhalt: ", ii.Count))
    93. End Function
    94. Private ENdl As New List(Of PointToPoint)
    95. Private Sub ZuL()
    96. Dim j As New Stopwatch
    97. j.Start()
    98. For Each WP_We As WP In zusammenfügen()
    99. ENdl.Add(New PointToPoint(WP_We))
    100. Next
    101. j.Stop()
    102. MessageBox.Show(String.Concat("Inhalt: ", ENdl.Count, "| Zeit: ", j.ElapsedMilliseconds))
    103. End Sub

    Dani=mc^2 schrieb:

    Und es geht immer noch nocht
    Ich sehe in Deinem Code keine Funktionalität, die parallelisierbar wäre. Wenn R.Next() nicht wäre, könntestb Du die äußere For-Schleife beim Pixel setzen parallelisieren.
    Dazu must Du zuerst allen Async-Code rausschmeißen.
    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!
    ich hab es jetzt anders gelöst mit weniger Traffic

    weil ich hatte ja immer riesen Datenmegen(Eine List(of) mit 99805 als count) die ich hin und her warf also dachte ich mir einfach mal kurz speichern und sehen was passiert

    edit nochmal jetzt läuft es perfekt
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing, System.Threading, System.IO, System.Drawing.Imaging, System.Runtime.InteropServices
    2. Public Class Form1
    3. Private R As New Random
    4. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    5. pixel_erstellen() 'hier zeine ich das bild
    6. End Sub
    7. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    8. Eintgragen()
    9. End Sub
    10. Public Structure PointToPoint
    11. Public Punktwert As WP
    12. Public x, y, xI, yI, xII, yII As Integer
    13. Public Tan_winkel, Abstand As Double
    14. Public Class Brechnung
    15. Public Shared Function Vergleich(Wert As Integer, WertI As Integer) As Integer
    16. If Wert < WertI Then Return WertI - Wert
    17. Return Wert - WertI
    18. End Function
    19. Public Shared Function Seite_c(a As Integer, b As Integer) As Double
    20. Return Math.Sqrt((a ^ 2) + (b ^ 2))
    21. End Function
    22. End Class
    23. Public Sub New(Pointe As WP)
    24. Punktwert = Pointe
    25. xI = Punktwert.PunktI.X
    26. yI = Punktwert.PunktI.Y
    27. xII = Punktwert.PunktII.X
    28. xII = Punktwert.PunktII.Y
    29. x = Brechnung.Vergleich(xI, xII)
    30. y = Brechnung.Vergleich(yI, yII)
    31. Tan_winkel = y / x
    32. Abstand = Brechnung.Seite_c(x, y)
    33. End Sub
    34. End Structure
    35. Public Structure WP
    36. Public PunktI, PunktII As Point
    37. Public Sub New(PI As Point, PII As Point)
    38. PunktI = PI
    39. PunktII = PII
    40. End Sub
    41. End Structure
    42. #Region "Pixel zeichen"
    43. Private Async Sub pixel_erstellen()
    44. gezeichnet = 0
    45. Await Task.Run(Sub()
    46. Dim bmp As New Bitmap(300, 300)
    47. For x As Integer = 0 To bmp.Width - 1
    48. For y As Integer = 0 To bmp.Height - 1
    49. Dim i As Integer = R.Next(10) 'pixel dichte
    50. If x Mod 2 = 0 Then
    51. bmp.SetPixel(x, y, Color.Black)
    52. gezeichnet += 1
    53. End If
    54. 'bmp.SetPixel(R.Next(0, 300), R.Next(0, 300), Color.Black)
    55. Next
    56. Next
    57. PictureBox1.Image = bmp
    58. End Sub)
    59. End Sub
    60. #End Region
    61. Private gess As Integer = 0
    62. Private gezeichnet As Integer = 0
    63. Private Iterator Function auslesen() As IEnumerable(Of PointToPoint)
    64. Dim Bild As Bitmap = New Bitmap(PictureBox1.Image)
    65. Dim wer As Boolean = False
    66. Dim LocI As New Point
    67. For x As Integer = 0 To Bild.Width - 1
    68. For y As Integer = 0 To Bild.Height - 1
    69. Dim k As Integer = Bild.GetPixel(x, y).ToArgb
    70. Select Case True
    71. Case Color.Black.ToArgb = k AndAlso Not wer
    72. LocI = New Point(x, y)
    73. wer = True
    74. Case Color.Black.ToArgb = k AndAlso wer
    75. gess += 1
    76. Yield New PointToPoint(New WP(LocI, New Point(x, y)))
    77. End Select
    78. Next
    79. wer = False
    80. Next
    81. End Function 'Gibt die Koordinaten der schwarzen Punkte durch
    82. 'MessageBox.Show(String.Concat("Inhalt: ", ENdl.Count, "| Zeit: ", j.ElapsedMilliseconds))
    83. Private l As New List(Of PointToPoint)
    84. Private Async Sub Eintgragen()
    85. gess = 0
    86. Dim k As New Stopwatch
    87. k.Start()
    88. Await Task.Run(Sub()
    89. For Each a As PointToPoint In auslesen()
    90. l.Add(a)
    91. Next
    92. End Sub)
    93. k.Stop()
    94. MessageBox.Show(String.Concat("Inhalt: ", l.Count, "| Zeit: ", k.ElapsedMilliseconds, "|Gesamt: ", gess, "|Gezeichnet: ", gezeichnet))
    95. End Sub
    96. Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    97. MessageBox.Show(String.Concat("Inhalt: ", l.Count))
    98. End Sub
    99. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    100. End Sub
    101. End Class

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Dani=mc^2“ ()