71 votes

Exceptions non gérées dans BackgroundWorker

Mon WinForms application utilise un certain nombre de BackgroundWorker objets à récupérer des informations à partir d'une base de données. Je suis en utilisant le BackgroundWorker, car il permet à l'INTERFACE utilisateur de rester débloqué lors des temps de l'exécution de requêtes de base de données et simplifie le modèle de thread pour moi.

Je suis occasionnelle DatabaseExceptions dans certains de ces threads d'arrière-plan, et j'ai vu au moins une de ces exceptions dans un thread de travail pendant le débogage. Je suis assez confiant, ces exceptions sont les délais d'attente qui je suppose que c'est raisonnable de s'attendre à ce que de temps en temps.

Ma question est à propos de ce qui se passe lorsqu'une exception non gérée se produit dans l'un de ces arrière-plan de threads de travail.

Je ne pense pas que je peux attraper une exception dans un autre thread, mais je peux attendre mon WorkerCompleted méthode à exécuter? Est-il de la propriété ou de la méthode du BackgroundWorker je peux interroger des exceptions?

77voto

Ed Guiness Points 21866

Si l'opération soulève une exception que votre code ne gère pas, l' BackgroundWorker des captures de l'exception et passe dans l' RunWorkerCompleted gestionnaire d'événements, où il est exposé à l'Erreur de la propriété de l' System.ComponentModel.RunWorkerCompletedEventArgs. Si vous êtes en cours d'exécution sous le débogueur de Visual Studio, le débogueur s'arrête au point dans le DoWork gestionnaire d'événement où l'exception non gérée s'est soulevé.

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.dowork.aspx

34voto

CallMeLaNN Points 1945

Je suis entièrement à l'aide de BackgroundWorker plus d'un ans et connaissent vraiment en profondeur.

Tout récemment, Mon RunWorkerCompleted n'attrape pas le e.Error quand je Throw New Exception("Test") en DoWork. Toutefois Exception non Gérée soulevées. Catch en DoWork n'est pas la meilleure pratique est donc e.Error eu aucun sens.

Lorsque j'essaie de créer de nouveaux Form avec de nouveaux BackgroundWorker, e.Error en RunWorkerCompleted traitées avec succès. Il devrait y avoir quelque chose de mal dans ma compliqué BackgroundWorker.

Après quelques jours de googler et de débogage, en essayant une erreur. J'ai trouvé ça dans mon RunWorkerCompleted:

  • Vérifiez e.Error d'abord, puis e.Cancelled et enfin e.Result
  • Ne pas obtenir l' e.Result si e.Cancelled = True.
  • Ne pas obtenir l' e.Result si e.Error n'est null (ou Nothing) **

** C'est là que je m'ennuie. Si vous essayez d'utiliser des e.Result si e.Error n'est null (ou Nothing), Unhandled Exception sera levée.


Mise à JOUR: Dans l' e.Result obtenir la propriété .NET conception de vérifier s' e.Error tout d'abord, si a reçu l'erreur, puis ils vont lever de nouveau la même exception de DoWork. C'est pourquoi nous obtenons une exception non Gérée dans RunWorkerCompleted mais en réalité, l'exception est venu de DoWork.

Ici est la meilleure pratique en RunWorkerCompleted:

If e.Error IsNot Nothing Then
  ' Handle the error here
Else
  If e.Cancelled Then
    ' Tell user the process canceled here
  Else
    ' Tell user the process completed
    ' and you can use e.Result only here.
  End If
End If

Si vous voulez un objet accessible à tous DoWork, ProgressChanged et RunWorkerCompleted, l'utiliser comme ceci:

Dim ThreadInfos as Dictionary(Of BackgroundWorker, YourObjectOrStruct)

Vous pouvez facilement accéder ThreadInfos(sender).Field n'importe où vous voulez.

10voto

Stu Mackellar Points 8605

Par défaut, il sera capturé et stocké par le BackgroundWorker. À partir de MSDN:

Si l'opération soulève une exception que votre code ne gère pas, le BackgroundWorker intercepte l'exception et passe dans le gestionnaire d'événements RunWorkerCompleted, où il est exposé à l'Erreur propriété du Système.ComponentModel.RunWorkerCompletedEventArgs. Si vous êtes en cours d'exécution sous le débogueur de Visual Studio, le débogueur s'arrête au point dans le DoWork gestionnaire d'événement où l'exception non gérée s'est soulevé.

4voto

Vedran Points 2107

Comme il a déjà été noté:

Si l'opération soulève une exception que votre code ne gère pas, la BackgroundWorker intercepte l'exception et passe dans la Gestionnaire d'événements RunWorkerCompleted, où il est exposé à l'Erreur propriété de Système.ComponentModel.RunWorkerCompletedEventArgs.

Ceci est important à chaque fois que vous interagissez avec le fil d'origine. Par exemple, si vous souhaitez que le résultat de votre exception à être écrits dans une sorte de label sur votre formulaire, c'est lorsque vous ne pouvez pas attraper l'exception dans le DoWork du BackgroundWorker, mais au lieu de la poignée de l'e.Erreur de RunWorkerCompletedEventArgs.

Si vous analysez le BackgroundWorker code avec réflecteur, vous pouvez voir tous ses traités assez simple: Votre DoWork est exécutée dans un bloc try-catch, et l'exception est passé juste à RunWorkerCompleted. Qui est la raison pour laquelle je suis en désaccord avec le "préféré" la méthode de toujours attraper toutes vos exceptions dans l'événement DoWork.

En bref, pour répondre à la question initiale:

Oui - vous pouvez compter sur votre RunWorkerCompleted de toujours être tiré.

L'utilisation de l'e.Erreur de RunWorkerCompleted pour vérifier les exceptions dans l'autre thread.

3voto

TzOk Points 31

Cela fonctionnera seulement sans le débogueur attaché, en actionnant de Visual Studio, le débogueur va intercepter l’exception dans la méthode DoWork et interrompt l’exécution, mais vous pouvez cliquer sur continuer et RunWorkerCompleted sera atteint et vous serez en mesure de lu exception grâce au champ e.Error.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X