Threadübergreifend auf Listview.items Auflistung zugreifen?

  • VB.NET

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Threadübergreifend auf Listview.items Auflistung zugreifen?

    Hallo in die Runde,

    ich bin neu hier und auch gleich mit einem Problem am Start;-)

    Folgender Sachverhalt:
    Ich habe ein Formular in welchem sich ein Listview befindet, in welchem auch Daten (items) vorhanden sind.

    Nun möchte ich gerne von einem anderen Thread aus auf dieses Listview zugreifen und die Itemaufzählung durchlaufen lassen, mit dem Ziel
    bestimmte iteminhalte auszulesen.

    Ich habe im Netz nur soviel herausgefunden, dass es etwas mit "invoke" und "delgate" zu tun haben muss

    Leider komme ich mit den Anweisungen "delagate" und "invoke" nicht mal ansatzweise klar. Die Erklärungen die ich im Netz gefunden habe treffen alle nicht auf mein Problem zu und verstehen konnte ich es auch nicht richtig.

    Könnte mir mal jemand - an Hand meines Falls - erklären wie ich das mit den beiden Anweisungen hinbekomme?

    Gruß, Thomas :)
    Selbe Problematik hatte ich vor ein paar Wochen auch;
    Die Lösung "Delegate"
    Schau dir das mal an..
    Thread:

    C#-Quellcode

    1. //deklaration
    2. public delegate void DelFileTransferInfo( int Procent );
    3. public event DelFileTransferInfo FileTransferInfo;
    4. //an der Stelle wo du es aufrufen willst
    5. FileTransferInfo(tmpCalc);


    Form:

    C#-Quellcode

    1. private delegate void DoSomething();
    2. void cc_FileTransferInfo( int Procent )
    3. {
    4. this.BeginInvoke(new DoSomething(delegate
    5. {
    6. //do what ever you want
    7. Update();
    8. }));
    9. }


    Natürlich musst du alles an deinen SC anpassen..
    Da ich im Internet selber kaum brauchbare Lösungen gefunden habe,
    hab ich es mal gepostet;
    Ich bin leider immer noch nicht viel weiter gekommen.
    Hier zur besseren Verdeutlichung mal ein Beispiel.


    VB.NET-Quellcode

    1. Public T As Thread


    VB.NET-Quellcode

    1. Sub lvAuslesen()
    2. 'NEUER Thread
    3. For Each item1 As ListViewItem In ListView1.items
    4. Select Case item1.Text
    5. Case Is = "1"
    6. Thread.Sleep(2000)
    7. Case Is = "2"
    8. Thread.Sleep(2000)
    9. Case Is = "3"
    10. Thread.Sleep(2000)
    11. Case Else
    12. Thread.Sleep(2000)
    13. End Select
    14. Next
    15. End Sub


    VB.NET-Quellcode

    1. 'Button im Form
    2. Sub Button1Click(sender As Object, e As EventArgs)
    3. T = New Threading.Thread(AddressOf lvAuslesen)
    4. T.Start
    5. End Sub


    Wenn das Button_Click event ausgelöst wird, wird der neue Thread gestartet in dem die Abfrage auf die Listview1.items erfolgt.

    Wie bekomme ich das hin, das der Thread unabhängig vom Haupttread läuft und diesen nicht blockiert?
    Also wenn der Nebenthread gerade Sleep(2000) ausführt soll der Hauptthread davon nicht beeinflusst werden.

    Ich hatte es so versucht. Da blieb aber auch der Haupttread stehen.

    VB.NET-Quellcode

    1. Sub lvAuslesen()
    2. Me.listView1.Invoke(Sub()
    3. For Each item1 As ListViewItem In ListView1.items
    4. Select Case item1.Text
    5. Case Is = "1"
    6. Thread.Sleep(2000)
    7. Case Is = "2"
    8. Thread.Sleep(2000)
    9. Case Is = "3"
    10. Thread.Sleep(2000)
    11. Case Else
    12. Thread.Sleep(2000)
    13. End Select
    14. Next
    15. End Sub)
    16. End Sub

    Gruß, Thomas

    VB.NET-Quellcode

    1. Me.Listview1.Invoke(Sub()Do Somphing end Sub)
    Hallo,

    In deinen zweiten Threadh den du hast, da ist der zugriff auf den UI Treadh ja "illegal", (CheckForIllegalThreadhCorssCalls = true), also musst du Invoken.

    Und das geht halt am besten wen du in der Sub den Coode (Lambada) einfügst.

    Das sieht dan in etwa so aus.

    VB.NET-Quellcode

    1. ​Public Class Form1
    2. Private Sub Form1_Load(ByVal sender as object, ByVal e as EventArgs) Handles Mybase.Load
    3. me.DoSomphing()
    4. end sub
    5. Sub DoSomphing()
    6. 'UI Thread
    7. Dim t as new Thread(AddressOf ZweiterTreadh)
    8. t.Start()
    9. end Sub
    10. Sub ZweitertThread()
    11. Me.Listview1.Invoke(Sub()
    12. Me.Listview1.items.Add("Ein neues Item)
    13. me.listview1.items(0).ForeColor = Color.Red
    14. ' Sonst was was du vorhast :D
    15. )
    16. end sub
    17. End Class


    LG, Herbrich

    zn-gong schrieb:

    VB.NET-Quellcode

    1. Me.Listview1.Invoke(Sub()Do Somphing end Sub)
    End Sub ist bei einem Einzeiler nicht nötig.


    tomxl01 schrieb:

    VB.NET-Quellcode

    1. Thread.Sleep(2000)
    Was soll das?
    Wenn ühaupt, genügt es, das vor dem Select Case genau ein Mal zu schreiben.
    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!

    zn-gong schrieb:

    CheckForIllegalThreadhCorssCalls = true

    Auch wenn der Boolean hier den richtigen Wert hat. Dieser Wort sollte nie nie nie nie nie jemand in den Mund nehmen, bevor einer auf die Idee kommt, es damit zu machen. (Just saying)
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Hallo,

    Das mit den End Sub ist mir sehr wohl bewusst aber der Editor bei vbp ist scheiße, er unterstüzt kein Tab, also habe ich das zweite beispiel in notepad gecoodet und dann C&P (Ich weiß CP ist hier nicht gerne gesehen^^ *IRONIE*)

    LG, Herbrich

    zn-gong schrieb:

    Hallo,

    In deinen zweiten Threadh den du hast, da ist der zugriff auf den UI Treadh ja "illegal", (CheckForIllegalThreadhCorssCalls = true), also musst du Invoken.

    Und das geht halt am besten wen du in der Sub den Coode (Lambada) einfügst.

    Das sieht dan in etwa so aus.

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Load(ByVal sender as object, ByVal e as EventArgs) Handles Mybase.Load
    3. me.DoSomphing()
    4. end sub
    5. Sub DoSomphing()
    6. 'UI Thread
    7. Dim t as new Thread(AddressOf ZweiterTreadh)
    8. t.Start()
    9. end Sub
    10. Sub ZweitertThread()
    11. Me.Listview1.Invoke(Sub()
    12. Me.Listview1.items.Add("Ein neues Item)
    13. me.listview1.items(0).ForeColor = Color.Red
    14. ' Sonst was was du vorhast :D
    15. )
    16. end sub
    17. End Class


    LG, Herbrich


    Soweit war ich doch schon mal. Bringt mich nicht wirklich weiter.
    Bei dieser Version reagiert das UI auch nicht mehr wenn ich den zweiten Thread "schlafen" lege --> deshalb auch die Sleeps von mir als Beispiel.
    Ich möchte ja gerne - das ist ja auch der Sinn von Mutithreading - dass der UI Thread weiterhin reagiert wenn ich den zweiten Tread mit etwas aufwendigem beschäftige, was z.b. das Listviewitem betreffen könnte.

    Gibt es denn dafür keine Lösung?


    @RodFromGermany:

    RodFromGermany schrieb:

    tomxl01 schrieb:
    VB.NET-Quellcode

    Thread.Sleep(2000)

    Was soll das?
    Wenn ühaupt, genügt es, das vor dem Select Case genau ein Mal zu schreiben.


    hast natürlich recht, Fehler von mir. Es reicht natürlich ein Sleep. Sollte ja auch nur ein Beispiel sein um zu zeigen, dass
    in dem Zweiten Thread was aufweniges passiert bei dem das Listview mit eingebunden ist.


    Gruß, Thomas
    Nat. geht das.
    Threads, ThreadPools (noch besser), Tasks, async-await.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Erstell doch einfach eine List of Listview Iteam und füge da alles hinzu und dann wen du mit den job fertig bist adde sie als letzte action in einen invokten teil im thread, das hat mir auch geholfen bei meinen facbook api project.

    LG, Herbrich

    Trade schrieb:

    Nat. geht das.
    Threads, ThreadPools (noch besser), Tasks, async-await.


    Aber genau das ist ja meine Frage gewesen, WIE genau soll ich das umsetzen?
    Sorry, aber Ich brauche da leider noch ein wenig Hilfestellung.
    Denn so wie oben beschrieben gehts bei mir definitiv nicht.

    Vielleicht sollte ich noch erwähnen was beim durcharbeiten der listviewitems, bei jedem item passiert.
    Es wird hier eine Prozedur aufgerufen in der ich Datenbankzugriffe realisiert habe, die Daten in eine DB importieren sollen.
    Deshalb auch der zweite Thread. Dann kann im UI zwischenzeitlich etwas anderes gemacht werden und es muss nicht auf die Fertigstellung der DB zugriffe warten.

    Vielen Dank für Eure Geduld

    Gruß, Thomas
    Google halt mal nen bisschen danach, da findest Du genügend zu Multithreading.
    Das könnte helfen:

    ​.NET Starting a new thread
    ​.NET ThreadPool.QueueUserWorkItem
    ​.NET TaskFactory.StartNew
    ​.NET async await (nur bei .NET 4.0/4.5)
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Hallo

    leider kann ich mit den Schlagwörtern oben bei "Trade" im Posting nicht viel anfangen.
    Soviel wuste ich bereits vor seinem Post.
    Was ich gerne gewusst hätte ist: wie realisiere ich das anhand meines Beispieles
    Ich bin eben ein NEULING was das Programmieren mit VB.NET angeht.
    Bis vor kurzem habe ich mich nur an VBA versucht und da war Multithreading kein Thema.

    Vielleicht kann sich doch noch jemand meiner erbarmen und mich mal konkret zu meinem hier präsentiertem Problem aufklären.

    Gruß, Thomas
    klar könnemer das für dich coden - lernste halt nix dabei. Tatsächlich hat zn-gong es schon gecodet, nur du weist nicht, wo einfügen.
    Ich weiß es auch nicht, denn du musst es ja bei dir einfügen.

    Also poste mal, was du bisher hast - aber lauffähig sollte es sein.
    Code es einfach, wie du es coden würdest, wenn du kein Threading bräuchtest.

    wichtig ist
    • erstens eine Methode, wo der Vorgang anfangen soll, etwa ein Button_Click-Ereignishandler
    • zweitens die Methode, die was tun soll. Die Start-Methode muss diese Tu-Methode aufrufen, und ihr die Daten übergeben
    Soweit erstmal - je nachdem, was zu tun ist, kommt evtl. noch eine 3. Methode hinzu.

    Dein Problem ist halt, dass du kaum Grundlagen hast.
    Ich hoffe, unter "Button_Click-Ereignishandler" kannst du dir ühaupt was vorstellen, und unter "Daten einer Methode übergeben"
    Hallo,

    Ich hoffe das war jetzt nicht falsch von mir das example zu cooden :(

    LG, Herbrich