| |
VB.NET - Ein- und UmsteigerListview 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 | |
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. | |
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. | |
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. | |
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 | |
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 | |
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 | |
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?
| |
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. | |
Re: Beispiel mit zwei Datentabellen | | | Autor: FEF | Datum: 09.02.16 11:02 |
| Habe ich bereits alles gemacht... | |
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. | |
Re: Listview Aktualisierungszeit und Backgroundworker | | | Autor: FEF | Datum: 10.02.16 18:24 |
| Dankeschön!
Hilft leider auch nicht viel... | |
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. | |
| 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 |
|
|
sevGraph (VB/VBA)
Grafische Auswertungen
Präsentieren Sie Ihre Daten mit wenig Aufwand in grafischer Form. sevGraph unterstützt hierbei Balken-, Linien- und Stapel-Diagramme (Stacked Bars), sowie 2D- und 3D-Tortendiagramme und arbeitet vollständig datenbankunabhängig! Weitere InfosTipp des Monats Access-Tools Vol.1
Über 400 MByte Inhalt
Mehr als 250 Access-Beispiele, 25 Add-Ins und ActiveX-Komponenten, 16 VB-Projekt inkl. Source, mehr als 320 Tipps & Tricks für Access und VB
Nur 24,95 EURWeitere Infos
|