none
BackgroundWorker RRS feed

  • Frage

  • Hallo zusammen,

    ich arbeite gerade an einer Visual Basic-Applikation, mit der man eine MySQL-Datenbank, die auf
    einem Webserver liegt, bearbeiten kann. (Einsatzzweck der fertigen Software: Vereinsmitglieder-Verwaltung !)

    Da die Voraussetzung für den Betrieb der Software eine funktionierende Internetverbindung ist, möchte ich in
    meiner Statusleiste den aktuellen Verbindungsstatus anzeigen. Zum einen soll diese Information einfach nur
    "VERBUNDEN!" oder "NICHT VERBUNDEN!" darstellen - eigentlich prüfe ich hier aber nur, ob der PC mit einem
    Netzwerk verbunden ist und nicht, ob dieses Netzwerk auch über Internet-Zugriff verfügt ... trotzdem:

      If My.Computer.Network.IsAvailable = False Then
           Verbindungsstatus.Text = "NICHT VERBUNDEN!"
      Else
           Verbindungsstatus.Text = "VERBUNDEN!"
      End If

    Des weiteren soll ich auch eine Art "Verbindungsqualitäts-Anzeige" angezeigt werden. Die Funktionsweise
    dieser funktioniert so: Ich führe 5 Pings hintereinander durch (ein Timeout von 250 ms pro Ping verhindert,
    dass dies ewig dauert ...). Im Anschluss wird mit einer Select Case - Anweisung ermittelt, wieviele der 5 Ping's
    erfolgreich waren und die Anzahl der erfolgreichen Ping's werden in einer Art Empfangsanzeige, wie man sie vom
    Handy kennt, ebenfalls in der Statusleiste angezeigt.

    Dim AnzahlPingOK As Integer = 0

    For PingCheck = 1 To 5 If My.Computer.Network.Ping("meineseite.com", 250) = True Then AnzahlPingOK += 1 End If Next PingCheck Select Case AnzahlPingOK Case 0 Me.Verbindungsqualität.Text = "○○○○○" Case 1 Me.Verbindungsqualität.Text = "●○○○○" Case 2 Me.Verbindungsqualität.Text = "●●○○○" Case 3 Me.Verbindungsqualität.Text = "●●●○○" Case 4 Me.Verbindungsqualität.Text = "●●●●○" Case 5 Me.Verbindungsqualität.Text = "●●●●●" End Select

    Da diese Überprüfung etwas Zeit und Rechenleistung in Anspruch nimmt, "hängt" während dieses Vorganges die Benutzeroberfläche jedoch - aus diesem Grund habe ich einen BackgroundWorker eingesetzt - und hier kommt das Problem:

    Zuerst mal der Code:

    Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork Dim AnzahlPingOK As Integer ' 1.) Check, ob Netzwerk verfügbar. Wenn kein Netz verfügbar Sub beenden, ' da sonst spätestens beim Ping-Test ein Laufzeitfehler auftritt ...

    If My.Computer.Network.IsAvailable = False Then Verbindungsstatus.ForeColor = Color.Maroon Verbindungsqualität.Text = "○○○○○" Exit Sub Else Verbindungsstatus.Text = "VERBUNDEN!" Verbindungsstatus.ForeColor = Color.ForestGreen End If ' 2.) "Verbindungsqualität" durch 5 Ping's ermitteln ...

    AnzahlPingOK = 0 For PingCheck = 1 To 5 If My.Computer.Network.Ping("sc-marchegg.at", 250) = True Then AnzahlPingOK += 1 End If Next PingCheck ' 3.) Ergebnis des Ping-Testes ausgeben ... Select Case AnzahlPingOK Case 0 Me.Verbindungsqualität.Text = "○○○○○" Case 1 Me.Verbindungsqualität.Text = "●○○○○" Case 2 Me.Verbindungsqualität.Text = "●●○○○" Case 3 Me.Verbindungsqualität.Text = "●●●○○" Case 4 Me.Verbindungsqualität.Text = "●●●●○" Case 5 Me.Verbindungsqualität.Text = "●●●●●" End Select End Sub

    Das "Problem" ist die im Quellcode markierte Zeile (Verbindungsstatus.ForeColor = Color.ForestGreen). Wenn ich diese nicht auskommentiere, fliege ich bei dieser Anwendung ohne Fehlermeldung einfach aus dem BackgroundWorker raus ... Wenn der BackgroundWorker zwecks Aktualisierung wieder von einem Timer zu Arbeiten beginnt, funktioniert aber wieder alles. Meine Frage ist, warum ich gerade beim 1. Ausführen des Workers an dieser Stelle aus der Sub "fliege" und es ab dem 2. Mal reibungslos funktioniert ...

    Vielen Dank bereits im Vorhinein für die Unterstützung ...

    Mittwoch, 26. Juni 2013 22:51

Antworten

  • Hallo patrick.r93,

    Dein Code aktualisiert die Benutzeroberfläche aus einem Hintergrundthread ohne jegliche Threadsynchronisierung. Das kann so nicht funktionieren. Zugriffe auf UI-Controls sind nur auf dem Thread erlaubt, auf dem die Steuerelemente erstellt wurden. Lies bitte die Hinweise in der Dokumentation zu BackgroundWorker. Verwende BackgroundWorker.ReportProgress() und aktualisiere im ProgressChanged-Handler die Benutzeroberfläche. Es wird garantiert, dass der ProgressChanged-Handler auf dem Thread aufgerufen wird, wo BackgroundWorker instanziert wurde. Außerdem solltest Du in DoWork() die Logik in ein Try...Catch...Finally-Konstrukt einbetten und im RunWorkerCompleted-Handler überprüfen, ob eine Ausnahme geworfen wurde. Zum Auffangen unbehandelter Ausnahmen verwende bitte AppDomain.UnhandledException.

    Gruß
    Marcel

    Donnerstag, 27. Juni 2013 05:23

Alle Antworten

  • Hallo patrick.r93,

    Dein Code aktualisiert die Benutzeroberfläche aus einem Hintergrundthread ohne jegliche Threadsynchronisierung. Das kann so nicht funktionieren. Zugriffe auf UI-Controls sind nur auf dem Thread erlaubt, auf dem die Steuerelemente erstellt wurden. Lies bitte die Hinweise in der Dokumentation zu BackgroundWorker. Verwende BackgroundWorker.ReportProgress() und aktualisiere im ProgressChanged-Handler die Benutzeroberfläche. Es wird garantiert, dass der ProgressChanged-Handler auf dem Thread aufgerufen wird, wo BackgroundWorker instanziert wurde. Außerdem solltest Du in DoWork() die Logik in ein Try...Catch...Finally-Konstrukt einbetten und im RunWorkerCompleted-Handler überprüfen, ob eine Ausnahme geworfen wurde. Zum Auffangen unbehandelter Ausnahmen verwende bitte AppDomain.UnhandledException.

    Gruß
    Marcel

    Donnerstag, 27. Juni 2013 05:23
  • Hallo Marcel,

    vielen Dank für deine Unterstützung !
    Jetzt funktioniert alles einwandfrei !

    Freundliche Grüße,
    patrick.r93

    Donnerstag, 27. Juni 2013 07:07