Dans une application WPF, j’ai une tâche d’access à la firebase database planifiée, exécutée périodiquement par un minuteur et cette tâche a été exécutée dans un thread BackgroundWorker.
Lorsque la tentative de connexion a échoué, je try_catch
une exception à l’ try_catch
construction try_catch
et je souhaite mettre à jour un texte de barre d’état dans un thread d’interface utilisateur.
Existe-t-il une construction d’événement de pré-construction dans BackgroundWorker
pour l’implémenter, quelque chose comme DoWorkEventHandler
ou RunWorkerCompletedEventHandler
, qui peut être utilisée pour cela? Si non, comment mieux le faire?
Edité (ajouté):
Si je veux gérer l’exception à l’intérieur de RunWorkerCompletedEventHandler
, en utilisant le paramètre e.Error
, cela ne fonctionne pas. Si je laisse une exception non gérée dans le thread BackgroundWorker
, l’application est suspendue et le débogueur pointe vers la chaîne de code qui est exécutée dans le thread BackgroundWorker
, en indiquant que: Exception n’a pas été gérée par le code utilisateur .
Ainsi, dans ce cas, le thread ne s’arrête pas, signalant à RunWorkerCompletedEventHandler
qu’il s’est arrêté avec une erreur, mais que l’application entière ne fonctionne plus.
Une interface utilisateur WPF peut être mise à jour à partir d’un thread en arrière-plan à l’aide de Dispatcher.BeginInvoke.
Par exemple, si votre code d’arrière-plan faisait partie d’une fenêtre, vous pouvez mettre à jour un TextBlock:
this.Dispatcher.BeginInvoke((Action)(() => { textBlock.Text = "Connection Failed!"; }));
Modifier:
Si votre code d’arrière-plan était dans une classe autre que votre fenêtre, vous pouvez créer une interface pour vous aider:
public interface IShowStatus { void ShowStatus(ssortingng message); }
Implémenter l’interface dans votre fenêtre
public void ShowStatus(ssortingng message) { this.Dispatcher.BeginInvoke((Action)(() => { textBlock.Text = message; })); }
Dans votre classe avec l’agent d’arrière-plan, créez une propriété pour contenir une référence à l’interface.
public IShowStatus StatusDisplay { get; set; }
Dans votre classe Window, initialisez la classe d’arrière-plan.
public void InitBackground() { BackgroundClass background = new BackgroundClass(); background.StatusDisplay = this; ...
Enfin, dans votre fil de discussion, vous pouvez dire:
StatusDisplay.ShowStatus("Connection Failed!");
La RunWorkerCompletedEventArgs e
de RunWorkerCompletedEventHandler
contient la propriété Error
celle-ci est de type Exception. Si aucune exception ne s’est produite pendant le travail du thread d’arrière-plan, le prpery a la valeur null. Sinon, il contient l’erreur qui s’est produite.
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Exception exceptionThrowDuringDoWorkEventHandler = e.Error; }
Définissez la propriété WorkerReportsProgress du travailleur d’arrière-plan sur true , puis ajoutez un gestionnaire d’événements pour l’événement ProgressChanged . Dans le code suivant, j’ai également ajouté un gestionnaire d’événements pour Form.Load.
Maintenant, essayez le code suivant:
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { MessageBox.Show(e.UserState.ToSsortingng()); } 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(); }
Si je veux gérer l’exception à l’intérieur de
RunWorkerCompletedEventHandler
, en utilisant le paramètree.Error
, cela ne fonctionne pas. Si je laisse une exception non gérée dans le threadBackgroundWorker
, l’application est suspendue et le débogueur pointe vers la chaîne de code qui est exécutée dans le threadBackgroundWorker
, en indiquant que: Exception n’a pas été gérée par le code utilisateur .Ainsi, dans ce cas, le thread ne s’arrête pas, signalant à
RunWorkerCompletedEventHandler
qu’il s’est arrêté avec une erreur, mais que l’application entière ne fonctionne plus.
Je suis très curieux à ce sujet. Essayez d’exécuter le code suivant dans une application de console et voyez si votre programme se bloque ou si l’erreur s’affiche dans le RunWorkerCompletedEventArgs
.
static void Main(ssortingng[] args) { var bw = new BackgroundWorker(); bw.DoWork += Bw_DoWork; bw.RunWorkerCompleted += Bw_RunWorkerCompleted; bw.RunWorkerAsync(); Console.ReadKey(); } private static void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { Console.WriteLine("Complete."); Console.WriteLine(e.Error); } private static void Bw_DoWork(object sender, DoWorkEventArgs e) { throw new NotImplementedException(); }