c# - Excepciones no controladas en BackgroundWorker
.net multithreading (5)
Como ya se señaló:
Si la operación genera una excepción que su código no maneja, BackgroundWorker captura la excepción y la pasa al controlador de eventos RunWorkerCompleted, donde se expone como la propiedad Error de System.ComponentModel.RunWorkerCompletedEventArgs.
Esto es importante siempre que estés interactuando con el hilo original. Por ejemplo, si desea que el resultado de su excepción se escriba en algún tipo de etiqueta en su formulario, es cuando no debe detectar la excepción en DoWork del BackgroundWorker, sino que debe manejar e.Error desde RunWorkerCompletedEventArgs.
Si analiza el código de BackgroundWorker con reflector, puede ver que todo se maneja de manera bastante sencilla: su DoWork se ejecuta en un bloque try-catch y la excepción acaba de pasar a RunWorkerCompleted. Esa es la razón por la que no estoy de acuerdo con el método ''preferido'' de capturar siempre todas tus excepciones en el evento DoWork.
En resumen, para responder la pregunta original:
Sí , puede contar con que su RunWorkerCompleted siempre será despedido.
Use e.Error de RunWorkerCompleted para verificar excepciones en el otro hilo.
Mi aplicación WinForms utiliza una serie de objetos BackgroundWorker para recuperar información de una base de datos. Estoy usando BackgroundWorker porque permite que la IU permanezca desbloqueada durante consultas de base de datos de larga ejecución y simplifica el modelo de subprocesamiento para mí.
Obtengo DatabaseExceptions ocasionales en algunos de estos subprocesos de fondo, y he sido testigo de al menos una de estas excepciones en un hilo de trabajo durante la depuración. Estoy bastante seguro de que estas excepciones son tiempos de espera que supongo que es razonable esperar de vez en cuando.
Mi pregunta es acerca de qué sucede cuando ocurre una excepción no controlada en uno de estos hilos del trabajador de fondo.
No creo que pueda detectar una excepción en otro hilo, pero ¿puedo esperar que se ejecute mi método WorkerCompleted? ¿Hay alguna propiedad o método del BackgroundWorker que pueda interrogar para excepciones?
Esto funcionará solo sin el depurador adjunto, cuando se ejecuta desde Visual Studio, el depurador detectará la excepción sin manos en el método DoWork y romperá la ejecución; sin embargo, puede hacer clic en continuar y se llegará a RunWorkerCompleted y podrá leer la excepción a través del campo e.Error.
Estoy usando BackgroundWorker
por completo durante años y realmente lo conozco en profundidad.
Recientemente, My RunWorkerCompleted
no RunWorkerCompleted
el e.Error
cuando simplemente e.Error
Throw New Exception("Test")
en DoWork
. Sin embargo Excepción no controlada planteada. DoWork
en DoWork
no es la mejor práctica, por lo tanto, e.Error
no tiene sentido.
Cuando intento crear un nuevo Form
con el nuevo BackgroundWorker
, e.Error
en RunWorkerCompleted
maneja con éxito. Debería haber algo mal en mi complicado BackgroundWorker
.
Después de unos días, busca y elimina errores, probando un error. Encontré esto en mi RunWorkerCompleted
:
- Compruebe primero
e.Error
, luegoe.Cancelled
y finalmentee.Result
- No obtenga
e.Result
sie.Cancelled = True
. - No obtenga el resultado
e.Result
sie.Error
no esnull
(oNothing
) **
** Aquí es donde extraño. Si intenta utilizar e.Result
si e.Error
no es null
(o Nothing
), se lanzará Excepción no controlada.
ACTUALIZACIÓN: En el e.Result
obtenga la propiedad del diseño .NET para verificar e.Error
primero, si obtuvo un error, entonces volverán a lanzar la misma excepción desde DoWork
. Es por eso que obtenemos la excepción no RunWorkerCompleted
en RunWorkerCompleted
pero en realidad la excepción proviene de DoWork
.
Esta es la mejor práctica para hacer 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 desea un objeto que sea accesible para todo DoWork, ProgressChanged y RunWorkerCompleted, use esto:
Dim ThreadInfos as Dictionary(Of BackgroundWorker, YourObjectOrStruct)
Puede acceder fácilmente a ThreadInfos(sender).Field
lugar que desee.
Por defecto, será capturado y almacenado por BackgroundWorker. Desde MSDN:
Si la operación genera una excepción que su código no maneja, BackgroundWorker captura la excepción y la pasa al controlador de eventos RunWorkerCompleted, donde se expone como la propiedad Error de System.ComponentModel.RunWorkerCompletedEventArgs. Si se ejecuta con el depurador de Visual Studio, el depurador se romperá en el punto en el controlador de eventos DoWork donde se produjo la excepción no controlada.
Si la operación genera una excepción que su código no maneja, BackgroundWorker
captura la excepción y la pasa al controlador de eventos RunWorkerCompleted
, donde se expone como la propiedad Error de System.ComponentModel.RunWorkerCompletedEventArgs
. Si se ejecuta con el depurador de Visual Studio, el depurador se romperá en el punto en el controlador de eventos DoWork donde se produjo la excepción no controlada.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.dowork.aspx