IndexOf liefert -1 für Items aus List(OfConnection) zurück (Mutli-Tcp-Server)

  • VB.NET

Es gibt 2 Antworten in diesem Thema. Der letzte Beitrag () ist von Minilulatsch.

    IndexOf liefert -1 für Items aus List(OfConnection) zurück (Mutli-Tcp-Server)

    Moin Leute,
    ich habe mal wieder ein Problem. Ich arbeite im Moment an einem Multi-Tcp-Server und benutze als Grundlage das Tutorial von Kevin89. Soweit funktioniert auch alles, die Verbindung wird problemlos hergestellt. Aber ich zeige euch mal lieber direkt wie mein Projekt bis jetzt aussieht (nur die wichtigen Ausschnitte)

    VB.NET-Quellcode

    1. Imports System.Net.Sockets
    2. Imports System.IO
    3. Imports System.Net
    4. Public Class Form1
    5. Dim Client As TcpClient
    6. Dim server As New TcpListener(IPAddress.Any, 1090)
    7. Dim c As New Connection
    8. Private list As New List(Of Connection)
    9. Private Structure Connection
    10. Dim stream As NetworkStream
    11. Dim streamw As StreamWriter
    12. Dim streamr As StreamReader
    13. End Structure
    14. Sub Connect()
    15. server.Start()
    16. Do
    17. Client = server.AcceptTcpClient
    18. c.stream = Client.GetStream
    19. c.streamr = New StreamReader(c.stream)
    20. c.streamw = New StreamWriter(c.stream)
    21. Dim ip = (Client.Client.RemoteEndPoint.ToString).Split("::")(0)
    22. list.Add(c)
    23. ListBox1.Items.Add(ip)
    24. Dim t As New Threading.Thread(AddressOf ListenToConnection)
    25. t.Start(c)
    26. Loop
    27. End Sub
    28. Private Sub ListenToConnection(ByVal con As Connection)
    29. con.stream = Client.GetStream
    30. con.streamw = New StreamWriter(con.stream)
    31. Do
    32. Try
    33. con.streamw.WriteLine("StillAlive")
    34. con.streamw.Flush()
    35. Catch ex As Exception
    36. ListBox1.Items.RemoveAt(list.IndexOf(con))
    37. list.Remove(con)
    38. Exit Do
    39. End Try
    40. Loop
    41. End Sub


    Vielleicht noch eine kurze Erklärung hinterher: Die Sub Connect (die übrigens beim Start des Programmes über einen Backgroundworker aufgerufen wird) startet den Server, nimmt einkommende Verbindung an, fügt sie zu "list" hinzu und fügt danach noch die Ip des Client zur Listbox1 hinzu. Dann wird ein neuer Thread gestartet der die Verbindung an ListenToConnection übergibt. Diese Sub soll den Status der Verbindung überprüfen indem er durchgehen "StillAlive" sendet. Wenn der Client geschlossen wird, schlägt der Sendevorgang fehl und die Verbindung soll in dem Catch-Block aus "list" und die angezeigte Ip aus Listbox1 entfernt werden.
    Meine Gedanke dahinter war, dass der Index von der Verbindung in "list" der gleiche ist wie der Index der angezeigten Ip in Listbox1, was theoretisch auch richtig ist. Aber hier tritt dann der Fehler auf. Erst mal ist überhaupt nichts passiert, weder bei "list" noch bei Listbox1 wurde etwas entfernt. Also bin ich auf Fehlersuche gegangen und hab dazu die Sub ListenToConnection zum folgenen abgeändert:

    VB.NET-Quellcode

    1. Private Sub ListenToConnection(ByVal con As Connection)
    2. ListBox1.Items.RemoveAt(list.IndexOf(con))
    3. list.Remove(con)
    4. End Sub


    Ich habe alles außer den Befehlen, bei denen eigentlich was passieren sollte, entfernt, sodass die Connection eigentlich direkt nachdem sie hinzugefügt wurde, wieder entfernt wird. Daraufhin wurde dann die Fehlermeldung ausgespuckt, dass der Wert bei list.IndexOf(con) = -1 sei. Dann ist es natürlich logisch warum nichts entfernt werden konnte, aber es erscheint mir völlig unlogisch wie dieser Wert -1 entsteht.
    Habt ihr eventuelle Ursachen dafür? Oder hat es eine spezielle Bedeutung wenn der Index eines Items -1 ist? Wäre nett, wenn ihr mir einige Vorschläge machen könntet :)
    Grüße,
    Minilulatsch
    Der Wert -1 heißt einfach nur, dass das gesuchte Objekt nicht gefunden wurde.

    [Edit]
    So, ich habe mir deinen Code mal genauer angeschaut und ihn angepasst.

    Ach und was mir auch noch aufgefallen ist, dass du versuchst, die Listbox direkt aus dem Thread heraus aufzurufen.
    Das wird zwangsläufig mit solch einer Fehlermeldung enden:
    "Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement ListBox1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde."

    Bitte lesen:

    Allerdings habe ich das auch schon mit eingebaut ;)

    Dann kommen wir mal zu dem Quellcode.

    Aber als erstes solltest du unbeding "Option Strict On" aktivieren.

    Threadsicheres Aufrufen von der Listbox

    VB.NET-Quellcode

    1. Enum ListboxEditMode
    2. addItem = 0
    3. removeItem
    4. End Enum


    VB.NET-Quellcode

    1. Delegate Sub ListboxEdit_Delegate(ByVal listbox As ListBox, ByVal editMode As ListboxEditMode, ByVal value As Object)
    2. Private Sub ListboxEdit(ByVal listbox As ListBox, ByVal editMode As ListboxEditMode, ByVal value As Object)
    3. If listbox.InvokeRequired Then 'Überprüfen ob eine Aufrufmethode aufgerufen werden muss
    4. Dim MyDelegate As New ListboxEdit_Delegate(AddressOf ListboxEdit) 'Delegaten definieren
    5. Me.Invoke(MyDelegate, New Object() {listbox, editMode, value}) 'Delegaten ausführen
    6. Else
    7. Select Case editMode 'Gewählten Bearbeitungsmodus feststellen
    8. Case ListboxEditMode.addItem 'Item zur Listbox hinzufügen
    9. listbox.Items.Add(value.ToString)
    10. Case ListboxEditMode.removeItem 'Item aus der Listbox entfernen
    11. listbox.Items.RemoveAt(Integer.Parse(value.ToString))
    12. End Select
    13. End If
    14. End Sub



    Sub Connect()

    VB.NET-Quellcode

    1. Sub Connect()
    2. Dim ip As String = ""
    3. server.Start()
    4. Do
    5. Client = server.AcceptTcpClient
    6. c.stream = Client.GetStream
    7. c.streamr = New StreamReader(c.stream)
    8. c.streamw = New StreamWriter(c.stream)
    9. ip = (Client.Client.RemoteEndPoint.ToString).Split(Char.Parse(":"))(0)
    10. list.Add(c)
    11. ListboxEdit(ListBox1, ListboxEditMode.addItem, ip)
    12. Dim ListenToConnectionT = New Threading.Thread(AddressOf ListenToConnection)
    13. ListenToConnectionT.Start(c)
    14. Loop
    15. End Sub


    Sub ListenToConnection(ByVal con As Object)

    VB.NET-Quellcode

    1. Private Sub ListenToConnection(ByVal con As Object)
    2. Dim listenCon As Connection = DirectCast(con, Connection)
    3. Do
    4. Try
    5. listenCon.streamw.WriteLine("StillAlive")
    6. listenCon.streamw.Flush()
    7. Catch ex As Exception
    8. ListboxEdit(ListBox1, ListboxEditMode.removeItem, list.IndexOf(listenCon))
    9. list.Remove(listenCon)
    10. Exit Do
    11. End Try
    12. Loop
    13. End Sub


    So läuft es bei mir einwandfrei :D


    MfG

    DarkAngel

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

    Erst mal entschuldigung das ich mich erst jetzt wieder melde^^
    Danke für deinen Vorschlag, ich werd mir erstmal die Seiten von oben durchlesen und dann bei Gelegenheit die Änderungen sofort ausprobieren. Das nut dem ungültigen threadübergreifender Vorgang wusste ich, dafür hatte ich im Quellcode eigentlich auch noch ein Checkforillegalcrossthreadcalls = False eingebaut, was zwar keine sehr gern gesehene Methode ist, aber für mich am einfachsten war. Deswegen hatte ich das auch nicht oben im Quellcode angeben.

    Aber vielen vielen Danke für deine Hilfe!!!

    Grüße,
    Minilulatsch

    [Edit]


    Deine Variante funktioniert wirklich perfekt! Nochmal ein großes Dankeschön an dich, jetzt muss ich mich nur noch ein bisschen mit dem neuen Quellcode beschäftigen, um ihn auch wirklich zu verstehen.

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