Multithread: Zugriff aus weiterem Thread auf Steuerelement im Hauptformular

  • VB.NET
  • .NET (FX) 4.0

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Multithread: Zugriff aus weiterem Thread auf Steuerelement im Hauptformular

    Hallo Leute

    Ich bin am Erstellen einer Anwendung, mit der ich nebenbei einen TCP.Listener einsetze.
    ( Listener aus Link : Multiserver (TCP))

    Hauptaufgabe:
    In Form1 Daten bearbeiten. -> OK, nichts spezielles.
    Nebenjob:
    Mit einem TcpListener auf Daten warten und diese in der Form in ein ListView schreiben, welches ich als Log-Ausgabe bestimmt habe. Kurz gesagt, ich möchte auf die empfangenden Daten im Form1 reagieren.

    Ich habe den TcpListener als Klasse eingesetzt.


    Aber: die Daten werden nicht in das Listview (als Log) ausgegeben, bzw. ich kann die empfangenen Daten nicht weiterverarbeiten.
    Wie wenn der Thread keinen Zugriff auf die Steuerelemente hätte . . . :S
    Im Debug-Modus kann ich die Daten ansehen . . .

    Genau: mir fehlen die Grundlagen für das <System.Threading>, wie man es richtig einsetzt.
    Nur..., finde ich einfach den Einstieg nicht.

    Kennt jemand eine Quelle dafür?

    Was habe ich bisher gemacht?

    Instanz der Klasse deklariert:

    VB.NET-Quellcode

    1. Public IPServ As New IPServer


    Aufrufen des Servers über einen Button

    VB.NET-Quellcode

    1. Try
    2. Dim Tasks As New IPServer()
    3. Dim Thread1 As New System.Threading.Thread(AddressOf IPServ.Run_IPServer)
    4. Thread1.Start()
    5. Catch ex As Exception
    6. MsgBox(Err.Description)
    7. End Try


    Im <Listen> bereich der Verbindung warte ich auf Daten und schreiben diese auf diverses Arten in das Programm zurück. Geht aber nicht. Alles bleibt leer:

    VB.NET-Quellcode

    1. Private Sub ListenToConnection(ByVal con As Connection)
    2. Do
    3. Try
    4. Dim tmp As String = con.streamr.ReadLine ' warten, bis etwas empfangen wird...
    5. Debug.Print(tmp)
    6. ' frmIP_Server.AddLineLog(tmp)
    7. ' AddLog(tmp, False)
    8. AddLog(tmp, False) ' Schreiben in eine globale Variable
    9. frmIP_Server.AddLineLog(tmp) ' Schreiben in das Log-Fenster
    10. SendToAllClients(con.nick & ": " & tmp) ' an alle clients weitersenden.
    11. Catch ' die aktuelle überwachte verbindung hat sich wohl verabschiedet.
    12. list.Remove(con)
    13. Console.WriteLine(con.nick & " has exit.")
    14. Exit Do
    15. End Try
    16. Loop
    17. End Sub


    Grüsse am Dienstag
    Lollipop

    lollipop schrieb:

    Wie wenn der Thread keinen Zugriff auf die Steuerelemente hätte
    Wenn du aus irgendeinem anderen Thread AUSSER dem UI Thread auf UI Elemente zugreifen willst, dann verwende einfach die Invoke Methode(msdn.microsoft.com/de-de/library/zyzhdc6b(v=vs.110).aspx), die alle Controls haben. Die wird von der Klasse Control(msdn.microsoft.com/de-de/libra…ms.control(v=vs.110).aspx) weiter vererbt. Diese bekommt als Parameter einen Delegaten (also entweder eine Funktion oder du machst das mittels Annonymer Methoden

    VB.NET-Quellcode

    1. Private Sub DoSomething()
    2. Me.listView1.Items.Clear()
    3. End Sub
    4. ' Aufruf:
    5. Me.listView1.Invoke(DoSomething)
    6. ' oder:
    7. Me.listView1.Invoke(Sub()
    8. DoSomething()
    9. End Sub)
    10. ' oder:
    11. Me.listView1.Invoke(Sub()
    12. Me.listView1.Items.Clear()
    13. End Sub)


    Und bitte fall nicht auf die Möglichkeit d'rauf rein CheckForIllegalCrossThreadCalls(msdn.microsoft.com/de-de/libra…hreadcalls(v=vs.110).aspx) auf True zu setzen. Das ist 1.) kein "guter Stil" und 2.) kann das zu Problemen bei gleichzeitigem Zugriff (der eine liest, während der andere schreibt) führen.

    Lg Radinator
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Danke für die Entscheidungshilfe.
    Das mit dem CheckForIllegalCrossThreadCalls habe ich gelesen + die dazugehörende Diskussion.
    Aber ich war mir doch nicht sicher, ob das mit dem Invoke das Richtige ist.

    Morgen schaue ich mir das genauer an.

    Gruss aus CH
    Lollipop
    Unterschied zwischen Invoke und BeginInvoke: stackoverflow.com/questions/22…en-invoke-and-begininvoke
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Ich merke, dass mein Wissen betreffend Klassen und Adressierung sehr beschränkt ist.

    Die Anwendung startet mit dem frmStart.
    Meine Log-Listbox befindet sich im frmStart.
    Für das Befüllen der ListBox verwende ich eine Sub, AddLog, welche einen neuen Eintrag erstellt und die veralteten Items löscht.

    Den IP-Listener (also der zusätzliche Thread) befindet sich in einer separaten Klasse und wird ab dem frmStart als neuer Thread gestartet.
    Aus diesem Thread will ich die ListBox über die Funktion AddLog befüllen.

    Mache ich im Thread eine neue Instanz des frmStart (wie hier beschrieben
    msdn.microsoft.com/de-de/library/zyzhdc6b(v=vs.110).aspx )
    wird wohl die Sub ausgeführt, schreibe ich wohl in die Instanz des Forms und nicht in das Form welches sichtbar vor mir liegt. Bin etwas ratlos.



    Ich muss mich zuerst um etwas anderes kümmern, komme in den nächsten Tagen auf das Thema zurück . . .

    Danke für eure Hilfe.

    lollipop schrieb:

    schreibe ich wohl in die Instanz des Forms und nicht in das Form welches sichtbar vor mir liegt.
    Das sieht mir nach Form1.DoIt() aus.
    Gugst Du hier.
    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!