Problem mit Databinding und typisiertem Dataset (Datagridview Bindingsource)

  • VB.NET
  • .NET (FX) 3.0–3.5

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von Veronesi.

    Problem mit Databinding und typisiertem Dataset (Datagridview Bindingsource)

    Hallo Zusammen

    Um Databinding und typisierte Datasets besser zu verstehen, bin ich gerade daran die Videos und Tutorials von @EDR durchzugehen.
    Dabei habe ich nun ein Problem.

    Zu Testzwecken habe ich mir ein Programm gemacht, in welches der Benutzer in ein Datagridview mehrere Hostnamen eintragen kann. Diese werden per Databinding ins Dataset geschrieben. Beim Beenden und Starten des Programmes werden die Daten in eine XML Datei geschrieben bzw. geladen. Dies funktioniert einwandfrei.


    Das Programm selbst geht alle Hostnamen im Dataset durch und pingt alle "gleichzeitig" an (Threadpool). Das Ergebnis des pings wird dann wiederum ins Dataset geschrieben.
    Da das Dataset beim schreiben synchronisiert werden muss, arbeite ich hier natürlich mit einem Synclock!

    Trage ich nun aber mehrere Hosts ein, so taucht nach ca. 30 Sekunden Laufzeit folgende Fehlermeldung auf:
    Trotz der Ausführlichen Fehlermeldung komme ich einfach nicht darauf, was mein Fehler ist.



    Es geht mir nicht so sehr um das Programm. Ich möchte also keine Kommentare wie: "Aber da gibt es bereits bessere Programme zum herunterladen". Es geht nur ums üben. Ich möchte verstehen, warum / was genau an meinem Programm falsch ist, dass ich diese Fehlermeldung erhalte.

    Das Programm ist im Anhang (im Bin Ordner ist die EXE entfernt, nur die Test-XML Datei ist dort mit den Einträgen).

    Vielen Dank für Eure Geduld.
    Veronesi
    Dateien
    • Multiping.zip

      (24,55 kB, 187 mal heruntergeladen, zuletzt: )
    Databinding greift auf Controls zu. Synclock reicht also nicht, sondern du musst das Einarbeiten nebenläufig generierter Daten ins gebundene Dataset zurück-verlegen in den Gui-Thread, mit control.BeginInvoke.

    Alternativ kannst du auch die BindingSources so lange suspendieren, mit BindingSource.RaiseListchangedEvent=False.
    Beim Rebinding musst du aber auch BindingSource.ResetBindings aufrufen, damit die nebenläufig durchgeführten Änderungen auch angezeigt werden.
    @ErfinderDesRades
    Vielen Dank für Deine sehr logische Erklärung.
    Das hat mir weitergeholfen.

    Ich habe nun im WriteData anstelle von SyncLock folgendes geschrieben:

    VB.NET-Quellcode

    1. For Each row As DataSet1.DataRow In DataSet1.Data.Rows
    2. If sHost = row.Server Then
    3. If Not DGV1.IsCurrentCellInEditMode Then
    4. Me.BeginInvoke(Sub()
    5. row.Result = Status
    6. row.Time = Time
    7. End Sub)
    8. End If
    9. End If
    10. Next


    Ist das soweit korrekt? (Es läuft nun immerhin ohne Fehlermeldung)

    Deine Alternative mit den BindingSources zu suspendieren, wollte ich vorerst nicht umsetzen, denn dann würden meine Einträge u.U. mehrere Sekunden nicht aktualisiert werden, wenn ein einzelner Ping länger braucht, bzw. ein Timeout hat.
    Aber sonst auch eine sehr gute Idee!

    Vielen Dank für Deine Hilfe
    Veronesi

    Edit:
    Vielleicht wüsstest Du auch noch eine Möglichkeit, die Zeilen je nach Resultat einzufärben?
    Im Code habe ich ja den Event DGV1.RowPrePaint abonniert. Mein Code ist dort allerdings aus kommentiert, da er natürlich nicht funktioniert.
    Wie kann ich in einem typisierten Dataset die Werte abfragen und die entsprechende Zeile einfärben?
    mach vernünftige Namen!
    Das Dataset darf nicht Dataset1 heissen, und die DataTable darin nicht Data, denn dadurch kommts zu Namensüberschneidung zw. der der typisierten Klasse DataSet1.DataRow und dem untypisierten System.Data.Datarow

    Verwende Typ-Inference, dann verfällst du etwas weniger leicht in untypisierte Programmierweise zurück.
    Poste immer ganze Methoden - in deim Snippet ist unklar, wo sHost, Status, Time herkommen, und welch Datentyp (naja, ich nehme String, String, Date an).

    Deine Schleife durchsucht im NebenThread die DataTable nach vmt. genau einer Datarow, aber nur wenn Dgv nicht im Editmodus, trägt sie Werte ein. Ok, das kann man effizienter organisieren:

    VB.NET-Quellcode

    1. Private Sub Inventarisize(ByVal server As String, ByVal status As String, ByVal time As Date)
    2. If DGV1.IsCurrentCellInEditMode Then Return 'braucht gar nicht erst zu suchen
    3. For Each rwPing In dtsServers.PingTest 'Typ-inference erkennt rwPing als PingTestRow
    4. If server = rwPing.Server Then
    5. Me.BeginInvoke(Sub()
    6. rwPing.Status = status
    7. rwPing.Time = time
    8. End Sub)
    9. Return 'kann Suche hier abbrechen
    10. End If
    11. Next
    12. End Sub

    Die ganze Suchschleife kann man sich evt. sparen, wenn man das Pingen als ObjektMethode der einzelnen PingTestRow anlegt.

    Zum Colorieren: Forumsuche "coloriertes Datagridview" - sollte auch im DB-Tut-Bereich rumfahren.

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

    Hallo @ErfinderDesRades

    Nochmals herzlichen Dank.
    Das ist eine wunderbare Hilfe!

    Das letzte Return von Dir allerdings lasse ich weg. Denn es könnte - theoretisch - sein, dass jemand den Server (warum auch immer) zweimal eingetragen hat. Und dann möchte ich alle Einträge aktualisieren.
    Ich weiss, mehrfache Einträge machen keinen Sinn und werde ich später noch abfangen. Aber momentan lasse ich das so.

    Vielen Dank nochmals!
    Super Hilfe!

    Veronesi