Arrayübertragung an Backgroundworker

  • VB.NET

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von Mono.

    Arrayübertragung an Backgroundworker

    Hallo!

    Heute habe ich wieder ein Problem.
    Ich zeige euch erstmal die wichtigen Ausschnitte aus meinem Code.

    VB.NET-Quellcode

    1. Public Class BGW_Uebergabe
    2. 'Diese Klasse dient der Übertragung von mehreren Arrays an den Backgroundworker-Threat
    3. Dim array1(7) As Byte
    4. Dim array2(3,5) As Byte
    5. Sub Array1speichern(ByVal wert As Array)
    6. array1 = wert
    7. End Sub
    8. Sub Array2speichern(ByVal wert As Array)
    9. array2 = wert
    10. End Sub
    11. Function Ausgabe_Array1(ByVal wert) As Array
    12. Ausgabe_Array1 = array1
    13. End Function
    14. Function Ausgabe_Array2() As Array
    15. Ausgabe_Array2 = array2
    16. End Function
    17. '...
    18. End Class
    19. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    20. 'Die Arrays (startarray bzw. endarray) werden durch Eingaben im Formfenster bestimmt.
    21. Dim Uebertragung As New BGW_Uebergabe
    22. Uebertragung.Array1speichern(startarray)
    23. Uebertragung.Array2speichern(endarray)
    24. Backgroundworker1.RunWorkerAsync(Uebertragung)
    25. 'Neues Objekt wurde erzeugt, die Arrays in dem Objekt gespeichert und der Backgroundworker gestartet (Das Objekt wurde mitübertragen)
    26. End Sub
    27. Private Sub Backgroundworker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles Backgroundworker1.DoWork
    28. 'Die Arrays werden aus dem übertragenen Porzess ausgelesen.
    29. Dim startwerte(7) As Byte
    30. Dim endwerte(3,5) As Byte
    31. Dim Uebertragungswerte As BGW_Uebergabe
    32. Uebertragungswerte = e.Argument
    33. startwerte = Uebertragungswerte.Ausgabe_Array1
    34. endwerte = Uebertragungswerte.Ausgabe_Array2

    So weit so gut. Ich habe schon überprüft, ob die Arraydaten wirklich ankommen, dass tun sie.

    VB.NET-Quellcode

    1. For i= 1 to 10000
    2. 'Jede Menge Auweisungen zur Auswertung der Arraydaten.
    3. 'Es wird qwasi eine Simultation für den Wert i durchgeführt, dabei werden die Werte von startwerte verändert.
    4. 'Wenn diese Simultation nicht erfolgreich wird, dann soll dieser Fall verworfen werden und die startwerte sollen neu aus dem Objekt
    5. 'Uebertragungswerte geladen werden.
    6. If SimultationErfolgreich()=True Then
    7. 'Ergebnis wird ausgegeben
    8. End Sub
    9. Else
    10. startwerte = Uebertragungswerte.Ausgabe_Array1
    11. Next i
    12. End Sub


    Ich bin jetzt durch mehrere Abfragen draufgekommen, dass mein Problem beim Übertragen der Arrays liegt. Irgendwie werden die Arrays refeziert, anstatt eine Kopie zu machen. Sobald ich in der Simultation eine Veränderung im Array startwerte mache, verändert sich auch das Array array1 in dem Objekt Uebertragungswerte. Ich habe auch schon die Befehle Clone und Copy probiert. Aber irgendwie werde ich nicht ganz schlau aus diesen. Es wird trotzdem refenziert.

    Kann mir einer bei diesem Problem helfen.

    Piakob schrieb:

    Irgendwie werden die Arrays refeziert, anstatt eine Kopie zu machen

    So ist es nunmal bei allen Objekten die auf dem Heap abgelegt werden: es werden bei Zuweisungen einfach immer nur die Zeiger auf die Objekte zugewiesen, veränderst Du also den Inhalt von einem Objekt verändert sich auch automatisch das andere.

    Das fängt schon bei Deiner Zuweisung Sub Array1speichern(ByVal wert As Array) an, veränderst Du danach irgendeinen Wert im Array Wert, so ändert sich auch das Array in Deiner Klasse.

    Um das zu vermeiden musst Du Dein neues Array wirklich Element für Element kopieren: entweder in einer Schleife oder mit dem Befehl .CopyTo.

    Noch ein paar Bemerkungen
    - manchmal tut man sich mit Arrays ohne feste Grenzen einfacher
    - statt der Functions solltest Du Dir vielleicht mal das Wissen über Properties anlesen
    - Du könntest (musst aber nicht) für den BGW eine Klasse anlegen , wobei die Arrays dann als Public Member definiert sind
    Übrigens:

    VB.NET-Quellcode

    1. Sub Any1(ByVal Feld() as Object)
    2. ...
    3. End Sub
    und

    VB.NET-Quellcode

    1. Sub Any2(ByRef Feld() as Object)
    2. ...
    3. End Sub
    behandeln Feld identisch als ByRef!
    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!

    RodFromGermany schrieb:

    Übrigens:

    VB.NET-Quellcode

    1. Sub Any1(ByVal Feld() as Object)
    2. ...
    3. End Sub
    und

    VB.NET-Quellcode

    1. Sub Any2(ByRef Feld() as Object)
    2. ...
    3. End Sub
    behandeln Feld identisch als ByRef!


    Das ist so nicht ganz richtig.
    Mit ByRef bei einem Referenztypen kannst du das Objekt auch neu referenzieren, mit ByVal eben nicht.


    Ein Beispiel was dies gut verdeutlicht:

    VB.NET-Quellcode

    1. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    2. Dim l As New List(Of String)
    3. l.Add("TEST")
    4. Any1(l)
    5. MsgBox(l.Count) 'Ausgabe = 1
    6. Any2(l)
    7. MsgBox(l.Count) ' Ausgabe = 0 ' da l neu Referneziert wurde
    8. End Sub
    9. Sub Any1(ByVal Feld As List(Of String))
    10. Feld = New List(Of String) ' ändert die Referenz nur innerhalb der Unterroutine
    11. End Sub
    12. Sub Any2(ByRef Feld As List(Of String))
    13. Feld = New List(Of String) 'ändert die Referenz auch ausserhalb dieser Unterroutine
    14. End Sub


    Gruss mono
    Das ist meine Signatur und sie wird wunderbar sein!