2010-02-20 12 views
8

In einer WPF-App habe ich eine geplante Datenbankzugriffsaufgabe, die regelmäßig von einem Timer ausgeführt wird, und diese Aufgabe wurde in einem BackgroundWorker-Thread ausgeführt.Wie behandelt man Ausnahmen von einem BackgroundWorker-Thread?

Wenn der Verbindungsversuch fehlgeschlagen ist, erhalte ich eine Ausnahme durch try_catch Konstruktion und ich möchte eine Statusleiste Text in einem UI-Thread aktualisieren.

Gibt es einige Prebuild-Ereigniskonstruktion in einem BackgroundWorker für die Implementierung dieser, so etwas wie DoWorkEventHandler oder RunWorkerCompletedEventHandler, die dafür verwendet werden können? Wenn nicht, wie geht es besser?

Edited (hinzugefügt):

Wenn ich die Ausnahme innerhalb RunWorkerCompletedEventHandler, mit e.Error Parameter zu handhaben wollen, ist es nicht funktioniert. Wenn ich Exception unbehandelt im Thread BackgroundWorker belasse, bleibt die Anwendung hängen und der Debugger zeigt auf die Code-Kette, die innerhalb BackgroundWorker Thread ausgeführt wird, mit der Aussage: Ausnahme wurde durch Benutzercode nicht behandelt.

Also, in diesem Fall stoppt Thread nicht nur, Signalisierung zu RunWorkerCompletedEventHandler, dass es mit Fehler gestoppt wurde, aber die ganze Anwendung funktioniert nicht mehr.

+0

Vielen Dank an alle für die Beantwortung! Unter Berücksichtigung einiger Antworten habe ich meine Frage mit weiteren Details aktualisiert. – rem

Antwort

5

Eine WPF-Benutzeroberfläche kann mithilfe von Dispatcher.BeginInvoke aus einem Hintergrundthread aktualisiert werden.

Zum Beispiel, wenn Ihr Hintergrund Code Teil eines Fensters war dann Sie einen Textblock aktualisieren könnte:

this.Dispatcher.BeginInvoke((Action)(() => 
    { 
     textBlock.Text = "Connection Failed!"; 
    })); 

Edit: machen Sie könnten

Wenn Ihr Hintergrund Code waren in einer anderen Klasse als Ihr Fenster eine Schnittstelle zu helfen:

public interface IShowStatus 
{ 
    void ShowStatus(string message); 
} 

Implementieren Sie die Schnittstelle in Ihrem Fenster

public void ShowStatus(string message) 
{ 
    this.Dispatcher.BeginInvoke((Action)(() => 
     { 
      textBlock.Text = message; 
     })); 
} 

In Ihrer Klasse mit dem Hintergrundarbeiter eine Eigenschaft machen, um einen Verweis auf die Schnittstelle zu halten.

public IShowStatus StatusDisplay { get; set; } 

Initialisieren Sie in Ihrer Window-Klasse die Hintergrundklasse.

public void InitBackground() 
{ 
    BackgroundClass background = new BackgroundClass(); 
    background.StatusDisplay = this; 
    ... 

schließlich in Ihrem Hintergrund-Thread kann man sagen:

StatusDisplay.ShowStatus("Connection Failed!"); 
+0

In meinem Fall ist der Hintergrundcode nicht Teil eines Fensters, sondern läuft in einer separaten Klasse. Außerdem findet die Ausnahme in einer statischen Methode statt. Daher ist dieses Schlüsselwort in diesem Fall nicht gültig. Bitte, helfen Sie mir zu verstehen, wie ich in diesem Fall mein Hauptfenster der Benutzeroberfläche referenzieren könnte? – rem

+0

Ich habe Notizen zu Ihrer Frage hinzugefügt. –

6

Die RunWorkerCompletedEventArgs e von RunWorkerCompletedEventHandler enthält Eigenschaft Error es ist von Typ Ausnahme. Wenn während der Arbeit des Hintergrund-Threads keine Ausnahme aufgetreten ist, hat der Prépery als Wert null. Sonst enthält es den Fehler, der aufgetreten ist.

3
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    Exception exceptionThrowDuringDoWorkEventHandler = e.Error; 
} 
+0

Wenn ich versuche, eine Ausnahme aus dem BackgroundWorker-Thread zu werfen, stürzt die App einfach ab: Exception wurde vom Benutzercode nicht behandelt. Ich komme nie zu bw_RunWorkerCompleted. Fehle ich etwas? – Doug

3

Stellen Sie die WorkerReportsProgress Eigenschaft des Hintergrundarbeiter wahr, dann einen Event-Handler für die Progress Ereignis hinzuzufügen.Im folgenden Code habe ich einen Ereignishandler für Form.Load hinzugefügt.

nun den folgenden Code:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) 
     { 
      MessageBox.Show(e.UserState.ToString()); 
     } 

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
      try 
      { 
       //some code that throws an exception 
       throw new NotImplementedException(); 
      } 
      catch (Exception ex) 
      { 
       backgroundWorker1.ReportProgress(0/*percent of progress*/, ex); 

      } 
     } 
     private void Form1_Load(object sender, EventArgs e) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
     } 
Verwandte Themen