Threadübergreifend in ListBox schreiben!

  • VB.NET

Es gibt 38 Antworten in diesem Thema. Der letzte Beitrag () ist von Manschula.

    das problem scheint mir aber anderweitig zu sein...
    kännte man mal den Code mit Methoden sehen?

    statt Dim Form1 As New Form

    evtl. einfach nur Form1.Invoke...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Klasse Form1: (mit der anzusprechenden Funktion)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Imports System.ComponentModel
    3. Imports System.Drawing
    4. Imports System.Math
    5. Class Form1
    6. Dim accounts As New List(Of String)
    7. Dim account_auswahl As New List(Of String)
    8. Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    9. 'unwichtiges zeug
    10. Melde_log("Willkommen")
    11. verteiler()
    12. End Sub
    13. Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_starten.Click
    14. Me.Controls.Remove(Me.PictureBox1)
    15. Me.Controls.Remove(Me.GroupBox1)
    16. Me.Controls.Remove(Me.GroupBox2)
    17. 'Me.Controls.Add(Me.PictureBox1)
    18. 'Me.Controls.Add(Me.GroupBox1)
    19. 'Me.Controls.Add(Me.GroupBox2)
    20. Me.Controls.Add(Me.GroupBox5)
    21. Me.Controls.Add(Me.GroupBox4)
    22. Me.Controls.Add(Me.GroupBox3)
    23. Me.TabControl1.SelectTab(3)
    24. Melde_log("Erfolgreich eingeloggt")
    25. End Sub
    26. Dim dummy As Object = ""
    27. Sub Melde_log(ByVal Meldung As String)
    28. SyncLock dummy
    29. Dim time As Date = TimeOfDay
    30. ListBox1.Items.Add("[" & time & ":] " & Meldung)
    31. ListBox1.SelectedIndex = ListBox1.Items.Count - 1
    32. Meldung = ""
    33. End SyncLock
    34. End Sub
    35. 'unwichtige Subs
    36. End Class


    Start des anderen Threads:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Friend w As New aktion()
    2. Friend Thread_aktion As New Thread(AddressOf w.start)
    3. Sub verteiler()
    4. Thread_aktion.Start()
    5. End Sub


    Klasse aktion mit dem delegaten in dem anderen Thread:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Delegate Sub d_melde_log(ByVal Meldung As String)
    2. Class aktion
    3. Friend c_meldung As New Form1
    4. Sub start()
    5. Try
    6. Dim melde_log_d As New d_melde_log(AddressOf c_meldung.Melde_log)
    7. 'melde_log_d.Invoke("TEST")
    8. Me.c_meldung.Invoke(melde_log_d, "Test")
    9. run = True
    10. Do
    11. Threading.Thread.Sleep(15)
    12. My.Application.DoEvents()
    13. Loop Until run = False
    14. Catch ex As Exception
    15. End Try
    16. End Sub
    17. End Class


    Form1.Invoke hab ich auch schon versucht... gleicher fehler
    wunderbar es geht! ABER ;D jetzt öffnet sich ein neues form, aber ich will ja in das vorhandene was schreiben?! hab auch schon c_meldung durch form1 ersetzt und ein form1.show gemacht...
    geht beides nur halt in einer neuen Instanz meines Porgramms, aber es soll ja in der ersten was verändert werden... (mache ich dieses .Show(), wird eine neue Instanz des GUI's erzeugt, aber durch das Form1_load event ist ja schon mein Form vorhanden...)
    mach Friend c_meldung As New Form1 mal ganz weg, überall da wo Fehler stehen, von wegen c_Meldung ist nicht deklariert(oder ähnlich), dort schreibst du Form1 hin, falls dieser Fehler in Form1 stehen sollte, schreibst du dort Me hin...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Gleiches Problem wie vorher:
    (alle c_meldung's aufrufe ersetzt durch Form1)

    Lasse ich das Form1.Show() vor dem Invoke aufruf weg, bekomme ich den fehler mit dem fensterhandle also wie vorher

    Mache ich das Form1.Show() hin, geht alles, aber dann hab ich 2 GUI's, die ursprüngliche verändert sich nun nicht mehr, die neue schreib jedoch "TEST" in "ihre" ListBox...

    EDIT://
    auch ein Form1.Show() im Form1_load event hat keine Besserung gebracht (kein 2. GUI aber der fehler vom anfang >.<)
    bringt alles nichts... nur wenn ich das Form1.Show() in den anderen Thread reinbaue (also vor das invoke) dann geht es.. ansonsten bekomme ich den fehler (wie immer):

    Quellcode

    1. Invoke oder BeginInvoke kann für ein Steuerelement erst aufgerufen werden, wenn das Fensterhandle erstellt wurde.
    [vb]
    Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Me.Show()
    'unwichtiges zeug

    Melde_log("Willkommen")

    verteiler()
    End Sub
    {/vb]
    und auch schon das Shown Event probiert?
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    VB.NET-Quellcode

    1. Private Sub Form1_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
    2. Me.Show()
    3. End Sub


    ja das auch... beides klappt nicht.. wie gesagt: nur wenn ich das in dem Thread vor dem invoke aufrufe geht es aber dann mit einer zweiten GUI...

    X( wiso kann das nicht einfach gehen :D:D

    VB.NET-Quellcode

    1. Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    2. 'unwichtiges zeug
    3. Melde_log("Willkommen")
    4. End Sub
    5. Private Sub Form1_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
    6. verteiler()
    7. End Sub

    beides kopierst du jetzt über das alte drüber ;)
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    ohjee :D dieser verteiler aufruf geschiet erst wenn ein button vom user gedrückt wird (ohje schlampig kopiert) und dieser button ist erst sichtbar, wenn das form geladen ist (und somit alles erstellt/sichtbar ist...)

    habe jetzt aber t.dem mal dein weg versucht (etwas umgeschrieben damit es so geht) aber auch das hat nicht geholfen :cursing: wenn das so weitergeht pack ich alles in 1 thread X( auch wenn ich dann jahre warten muss, bis das GUI Thread mal die GUI aktualisieren darf und andersrum 8|
    wie sieht denn dann der Code wirklich aus?(wie kann man Schlampig kopieren?^^)

    Me.Controls.Add(Me.GroupBox5)
    Me.Controls.Add(Me.GroupBox4)
    Me.Controls.Add(Me.GroupBox3)

    außerdem wird das wohl kaum funktionieren, da diese bereits hinzugefügt sind, du solltest dir mal die Visible Eigenschaft angucken...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---

    jvbsl schrieb:

    wie sieht denn dann der Code wirklich aus?(wie kann man Schlampig kopieren?^^)

    Me.Controls.Add(Me.GroupBox5)
    Me.Controls.Add(Me.GroupBox4)
    Me.Controls.Add(Me.GroupBox3)

    außerdem wird das wohl kaum funktionieren, da diese bereits hinzugefügt sind, du solltest dir mal die Visible Eigenschaft angucken...
    ich habe den ganzen müll, der nichts mit dem problem zu tun hat rausgeschmissen...
    Diese sachen sind noch nicht hinzugefügt (habe das add aus dem form.designer.vb rausgenommen und füge sie erst da hinzu (das programm hat am anfang ein aussehn, aber das wird nur einmal verwendet, das zweite (was ich hier hinzufüge) ist dann jedoch das endgültige, deswegen hab ich es nicht mit visible gemacht...

    Würde es evtl etwas helfen, wenn ich die funktionen des 2. Threads in die Klasse Form1 reinpacke und dann den thread dort starte? (denn evtl liegt es ja an den verschiedenen klassen der threads, wie hier schonmal vermutet wurde..?)

    edit >.<: morgen mach ich weiter... muss früh raus

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

    kann ich mir nicht vorstellen(schließlich gab es bei mir auch noch nie Probleme Klassenübergreifend mit Threads zu arbeiten...)
    (aber zur Sicherheit würde ich es trotzdem mal probieren...)

    warum steht verteiler in Form_Load, wenn du es anscheinend erst bei einem Button Click aufrufst? Außerdem sehe ich nirgends den Button, wo dies geschieht?!
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Ich denke du solltest dir den Aufbau deines Projekts nochmal durch den Kopf gehen lassen.
    Auch diese Verschachtelung zweier Klassen ist doch total unstrukturiert.

    Du rufst eine Methode aus deiner einen Klasse auf, die wiederum per Delegate eine Methode aus deiner Ausgangsklasse aufruft.. das ist total unübersichtlich und nicht durchdacht.

    Am besten benutzt du dafür ein Event. Baust dir dafür deine eigene EventArgs Klasse, und kannst dann in deiner Form Klasse auf die Events reagieren.
    Mit den Eventargs kannst du alle Möglichen Daten übergeben.
    Dann hast du die Möglichkeit entweder aus der Form Klasse per Delegaten auf die GUI aus dem Event herraus zuzugreifen oder du schaust dir den AsyncManager an oder DynamicInvokes.


    Mal ein Beispiel...

    VB.NET-Quellcode

    1. Imports System.Threading
    2. Public Class Form1
    3. Private WithEvents w As aktion
    4. Delegate Sub d_melde_log(ByVal Meldung As String)
    5. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    6. w = New aktion
    7. Dim Thread_aktion As New Thread(AddressOf w.starte)
    8. Dim time As Date = TimeOfDay
    9. Thread_aktion.Start()
    10. End Sub
    11. Private Sub aktion_SendeMeldung(ByVal e As MyEventArgs) Handles w.SendeMeldung
    12. Me.Invoke(New d_melde_log(AddressOf Me.Melde_log), e.Meldung)
    13. End Sub
    14. Public Sub Melde_log(ByVal Meldung As String)
    15. Dim time As Date = TimeOfDay
    16. ListBox1.Items.Add("TEST")
    17. ListBox1.Items.Add("[" & time & ":] " & Meldung)
    18. ListBox1.SelectedIndex = ListBox1.Items.Count - 1
    19. Me.Text = "TEST"
    20. End Sub
    21. End Class
    22. Public Class MyEventArgs
    23. Inherits System.EventArgs
    24. Private _meldung As String
    25. Public Property Meldung() As String
    26. Get
    27. Return _meldung
    28. End Get
    29. Set(ByVal value As String)
    30. _meldung = value
    31. End Set
    32. End Property
    33. Public Sub New(ByVal _Meld As String)
    34. Meldung = _Meld
    35. End Sub
    36. End Class
    37. Public Class aktion
    38. Public Event SendeMeldung(ByVal e As MyEventArgs)
    39. Friend Sub starte()
    40. Try
    41. For a As Integer = 0 To 5
    42. Threading.Thread.Sleep(200)
    43. Next
    44. RaiseEvent SendeMeldung(New MyEventArgs("MEINE MELDUNG"))
    45. Catch ex As Exception
    46. RaiseEvent SendeMeldung(New MyEventArgs(ex.Message))
    47. End Try
    48. End Sub
    49. End Class
    Das ist meine Signatur und sie wird wunderbar sein!

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

    so :) nach ein paar umbauarbeiten hab ich jetzt alles so umgebaut und das mit dem event eingefügt :) wunberbar! Es geht endlich!! die meldung, die ich in meinem 2. thread absende erscheint in der listbox :)

    DANKE an alle die mir geholfen haben :)

    Jetzt hab ich aber noch eine andere Frage:
    Wie kann ich mithilfe dieser Events zum Beispiel den Hintergrund einer Picturebox aktualisieren lassen? (hab mich noch nie so wirklich mit events befasst :rolleyes: , eine gutes beispiel mit erklärung würde mir auch schon helfen :) und ich werde nacher mal in der Hilfe lesen :))

    @jvbsl:
    nach den Umbauarbeiten ist das ganze nun wesentlich geordneter :rolleyes: