vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Brandneu! sevEingabe v3.0 - Das Eingabecontrol der Superlative!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Ein- und Umsteiger
Listview Aktualisierungszeit und Backgroundworker 
Autor: FEF
Datum: 08.02.16 11:06

Hallo!

Ich versuche einen Datenlogger zu basteln, der mir die Kommunikation zwischen 2 Geräten loggt.
Dazu verwende ich ein Listview das im Sekundentakt mit den Daten (AddRange) gefüllt wird. Die Netzwerkkommunikation habe ich mit Backgroundworker realisiert.
So weit funktioniert alles einwandfrei, ein Problem gibt es nur bei ganz schnellen Abfragen.
Immer wenn das Listview aktualisiert wird (Sekundentakt), dann arbeiten im Hintergrund auch die Backgroundworker nicht, was dazu führt dass es zu diesen Zweitpunkt auch keine Kommunikation im Hintergrund gibt.

Mit einer TextBox oder Richtextbox würde das schon funktionieren, nur ich möchte die Daten in Spalten aufschlüsseln und ansprechend darstellen.

Wie kann ich erreichen dass die Backgroundworker zum Zeitpunkt der Listview- Daten Aktualisierung weiter laufen?

Grüße, FEF
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Listview Aktualisierungszeit und Backgroundworker 
Autor: Manfred X
Datum: 08.02.16 12:20

Hallo!

Verwende eine Datenquelle z.B. DataTable, um die Daten im Hintergrund-
prozess einzutragen. Die Aktualisierung der Datenbindung (z.B. DatagridView)
läuft dann per Invoke/Binding-Reset im UI-Thread.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Listview Aktualisierungszeit und Backgroundworker 
Autor: FEF
Datum: 08.02.16 13:45

Hallo Manfred!

Vielen Dank für deinen Tipp!
Mit einem Datagridview und DataBinding/Reset für die Aktualisierung habe ich es auch schon versucht, das funktioniert bei mir überhaupt nicht gut, ist noch viel langsamer als bei einem Listview.
Also wie gesagt, die Backgroundworker (BGW) sind bei der Aktualisierung (UI Thread/BindingReset) wie eingefroren.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Listview Aktualisierungszeit und Backgroundworker 
Autor: Manfred X
Datum: 08.02.16 14:00

Koppel den Oberflächen-Thread (Anzeige) ab.
Lass' einen Timer z.B. im 5 Sekunden-Takt eine
Reset-Methode der Bindingsource ausführen.
Die Datenbindung kann während des Warteintervalls
suspendiert werden.

Beitrag wurde zuletzt am 08.02.16 um 14:05:46 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Beispiel mit zwei Datentabellen 
Autor: Manfred X
Datum: 08.02.16 15:35

Public Class frmBackground
 
    Dim dt As New DataTable
    Dim dt_display As DataTable
 
    Dim dgv As New DataGridView With _
         {.Parent = Me, .Width = 400, .Height = 400}
 
    Dim createdata As New _
        Threading.Thread(AddressOf CreateDataRows)
 
 
    Private Sub frmBackground_Load(sender As System.Object, _
                          e As System.EventArgs) Handles MyBase.Load
 
        'Spalten und Zeilen erstellen
        dt.Columns.Add("ID", GetType(Integer))
        For i As Integer = 1 To 10
            dt.Columns.Add("SP" & CStr(i))
        Next i
 
        For i As Integer = 1 To 100
            dt.Rows.Add(dt.NewRow)
        Next i
 
        dt_display = dt.Copy
        dgv.DataSource = dt_display
 
        Me.Size = New Size(500, 500)
        Me.Show()
 
        'Prozess für schnelle Datenerzeugung
        createdata.Start()
 
    End Sub
 
 
    Private Sub CreateDataRows()
 
        Dim id, rowindex As Integer
        Dim lasttime As DateTime
        Do
            id += 1 : rowindex += 1
            If rowindex = dt.Rows.Count Then
                'Umlaufender Index der Tabellenzeilen
                rowindex = 0
            End If
 
            'Zeile neu mit Daten füllen 
            Dim row As DataRow = dt.Rows(rowindex)
            row(0) = id
            For i As Integer = 1 To 10
                row(i) = i.ToString & ": " & id.ToString
            Next i
 
            If Date.Now.Ticks - lasttime.Ticks > _
                TimeSpan.TicksPerSecond Then
 
                'In Intervallen die aktuellen Daten anzeigen
                Me.Invoke(New MethodInvoker(AddressOf Displaydata))
                lasttime = Date.Now
            End If
        Loop While id < 10000000
 
    End Sub
 
 
    Private Sub Displaydata()
 
        dgv.DataSource = Nothing
 
        dt_display.Dispose()
        'Datentabelle für Anzeige klonen
        dt_display = dt.Copy
 
        dgv.DataSource = dt_display
    End Sub
End Class
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Beispiel mit zwei Datentabellen 
Autor: FEF
Datum: 08.02.16 18:15

Hallo Manfred!

Danke nochmal für deine Unterstützung! http://www.vbarchiv.net/images/smilies/smiley14.gif
Ich habe deinen Code ausprobiert, er funktioniert auch einwandfrei, nur gibt es dabei folgende Nachteile:
1. Das Datagrid wird immer nur mit den letzten Daten gefüllt, vorherige Einträge werden immer gelöscht, was bei einem Datenlogger ja nicht so gut ist.
2. Verhindert man ein löschen(dt_display.merge) kommt das Datagrid nicht mehr mit den Aktualisierungen nach...
3. dgv.DataSource = Nothing... siehe Punkt 1 und 2, und ohne "nothing" steigt die Zeit natürlich extrem...
4. Displaydata() läuft auch im UI Thread, der ja bei der Aktualisierung des DGV bewirkt dass der BGW in dieser Aktualisierungszeit "einfriert".


http://www.vbarchiv.net/images/smilies/smiley10.gif
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Beispiel mit zwei Datentabellen 
Autor: Manfred X
Datum: 08.02.16 20:32

In diesem Beispiel wird eine Tabelle "dt" fortlaufend gefüllt.
In Zeitabständen von 5 Sekunden werden die letzten 200 Zeilen
aus "dt" in die zuvor gelöschte Display-Tabelle eingetragen
(Import) und im Grid angezeigt.
Public Class frmBackground
 
    Dim dt As New DataTable  'fortlaufende Tabelle
    Dim dt_display As DataTable
 
    'anzuzeigende Zahl der Zeilen
    Const RowsToDisplay As Integer = 200
 
    Dim dgv As New DataGridView With _
        {.Parent = Me, .Width = 400, .Height = 400}
 
    Dim createdata As New Threading.Thread(AddressOf CreateDataRows)
 
 
    Private Sub frmBackground_Load(sender As System.Object, _
                             e As System.EventArgs) Handles MyBase.Load
 
        'Spalten und Zeilen erstellen
        dt.Columns.Add("ID", GetType(Integer))
        For i As Integer = 1 To 10
            dt.Columns.Add("SP" & CStr(i))
        Next i
 
        'Tabellenschema übertragen
        dt_display = dt.Clone
 
        Me.Size = New Size(500, 500)
        Me.Show()
 
        'Prozess für schnelle Datenerzeugung
        createdata.Start()
 
    End Sub
 
 
    Private Sub CreateDataRows()
 
        Dim id As Integer
        Dim lasttime As DateTime
        Do
            id += 1
 
            'neue Zeile mit Daten füllen 
            Dim row As DataRow = dt.NewRow
            row(0) = id
            For i As Integer = 1 To 10
                row(i) = i.ToString & ": " & id.ToString
            Next i
            dt.Rows.Add(row)
 
            If Date.Now.Ticks - lasttime.Ticks > _
                5 * TimeSpan.TicksPerSecond Then
 
                'In Intervallen die aktuellen Daten anzeigen
                Me.Invoke(New MethodInvoker(AddressOf Displaydata))
                lasttime = Date.Now
            End If
        Loop While id < 10000000
    End Sub
 
 
    Private Sub Displaydata()
        'Datenbindung unterbrechen
        dgv.DataSource = Nothing
        'Display-Table im Hintergrund füllen
        Dim fill As New Threading.Thread(AddressOf FillDisplayTable)
        fill.Start()
    End Sub
 
 
    Private Sub FillDisplayTable()
 
        Dim lastindex As Integer = dt.Rows.Count - 1
        Dim startindex As Integer = _
            Math.Max(lastindex - RowsToDisplay, 0)
 
        dt_display.Clear()
 
        For i As Integer = startindex To lastindex
            dt_display.ImportRow(dt.Rows(i))
        Next i
 
        'Datenbindung herstellen
        Me.Invoke(New MethodInvoker(AddressOf ShowData))
    End Sub
 
 
    Private Sub ShowData()
        dgv.DataSource = dt_display
        dgv.FirstDisplayedScrollingRowIndex = _
          dt_display.Rows.Count - 1
    End Sub
End Class
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Beispiel mit zwei Datentabellen 
Autor: FEF
Datum: 09.02.16 10:33

Hallo Manfred!

Danke für deine Bemühungen!
Ich bin zur Kenntnis gekommen dass man ein Datagridview nur halbwegs schnell füllen kann wenn "dgv.DataSource = Nothing" vor der Aktualisierung immer wieder gesetzt wird. Dann kann man aber auch nicht während des loggens scrollen, zumindest nur so lange bis das DGV aktualisiert wird.
Wie schon anfangs beschrieben funktioniert die Lösung mit einem Listview recht gut, es flackert nicht, stellt die Daten ansprechend dar, und ist relativ schnell- eigentlich perfekt, wenn ich eben diese Aktualisierungszeit ("friert" ca. 200mS die BGW) noch irgendwie pimpen könnte?

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Beispiel mit zwei Datentabellen 
Autor: Manfred X
Datum: 09.02.16 10:53

Um das Listview schnell zu aktualisieren und zu zeichnen:
Setze die DoubleBuffered-Eigenschaft des Formulars auf true
und sammle die neuen Zeilen (ListViewitems/Array) zunächst separat und
verwende für die Anzeige eines "Zeilenpakets" die "Addrange"-Methode
der "Items"-Auflistung dieses Controls.
Sonst fällt mir in dem Zusammenhang leider keine Optimierung ein.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Beispiel mit zwei Datentabellen 
Autor: FEF
Datum: 09.02.16 11:02

Habe ich bereits alles gemacht...
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Beispiel mit einer Datentabelle 
Autor: Manfred X
Datum: 09.02.16 11:10

Ansonsten:
Sperre ggf. temporär die Ereignishandler der ListView-Events,
die Du erstellt hast.

Wenn die Datenmengen überschaubar sind und die
Geschwindigkeit nicht zu schnell ist, kannst Du diese
Variante probieren.

Public Class frmBackground_II
 
    Dim dt As New DataTable
    Dim bs As New BindingSource With {.RaiseListChangedEvents = True}
 
    Dim dgv As New DataGridView With {.Parent = Me, .DataSource = bs, _
                         .AllowUserToAddRows = False, .ReadOnly = True}
 
 
    Dim createdata As New Threading.Thread(AddressOf CreateDataRows)
 
 
    Private Sub frmBackground_II_Load(sender As System.Object, _
                            e As System.EventArgs) Handles MyBase.Load
 
        Me.DoubleBuffered = True
 
        'Tabellen-Spalten erstellen
        dt.Columns.Add("ID", GetType(Integer))
        For i As Integer = 1 To 10
            dt.Columns.Add("SP" & CStr(i))
        Next i
 
        Me.Size = New Size(500, 500)
        Me.Show()
 
        bs.DataSource = dt
 
        'Prozess für schnelle Datenerzeugung
        createdata.Start()
 
 
    End Sub
 
 
    Private Sub CreateDataRows()
        Dim rndm As New Random, id, lastid As Integer
 
        Do
            id += 1
            Dim waittime As Integer = CInt(rndm.NextDouble * 10)
            Threading.Thread.Sleep(waittime)
 
            'neue Zeile mit Daten füllen 
            Dim row As DataRow = dt.NewRow
            row(0) = id
            For i As Integer = 1 To 10
                row(i) = i.ToString & ": " & id.ToString
            Next i
            dt.Rows.Add(row)
 
 
            If id > lastid + 20 Then
                Me.Invoke(New MethodInvoker(AddressOf showdata))
                lastid = id
            End If
        Loop While id < 100000
    End Sub
 
 
    Private Sub showdata()
        SyncLock bs.SyncRoot
            bs.ResetBindings(False)
            dgv.Update()
            dgv.FirstDisplayedScrollingRowIndex = bs.Count - 1
        End SyncLock
    End Sub
End Class


Beitrag wurde zuletzt am 09.02.16 um 11:30:03 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Listview Aktualisierungszeit und Backgroundworker 
Autor: FEF
Datum: 10.02.16 18:24

Dankeschön!
Hilft leider auch nicht viel...
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Listview Aktualisierungszeit und Backgroundworker 
Autor: Manfred X
Datum: 11.02.16 06:52

Vielleicht ist ein Projekt des Typs Windows-Presentation-Foundation
für Deine Zwecke eher angemessen.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Sie sind nicht angemeldet!
Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel