There is no code to catch the error. The Execute() method exits long before the error is thrown. Even if it had a sleep, it would not catch the error. You need to use a task wait or async/await to catch the error. note: one thread can not catch another’s error. You need check the status of the task after completion, to detect and rethink the error. This is what wait() and await do.
WPF: Why BackgroundWorker.RunWorkerCompleted Event() throw an exception and main thread does not receive it?
Our WPF application targets .NET 4.8.
The AbortableBackgroundWorkder class inherences from the BackgroundWorker class and used as following.
there are two background workers:
_protocolProcessorBackgroundWorker..DoWork() will call {
_protocolProcessorMacro.Execute(_protocolProcessorBackgroundWorker.Token);
}
_protocolProcessorBackgroundWorker.RunWorkerAsync();
_protocolProcessorMacro.Execute() will call {
pcrBackgroundWorker.DoWork += (, __) => { _pcrMacro.Execute(_pcrBackgroundWorker.Token); };
}
_pcrBackgroundWorker.RunWorkerAsync();
when _pcrMacro.Execute() has occurred an exception, it went through "_pcrBackgroundWorker.RunWorkerCompleted()" event with following black code.
// Exception occurred
if ( e.Error != null )
{
WriteToRunLog( "!! PCR Exception " + e.Error.Message );
throw e.Error;
}
However, "throw e.Error;" seems hidden and did not receive by ProtocolProcessorMacro catch block.
so ProtocolProcessorMacro continues to next macro "transferPcrMacro.Execute();"
what cause that "throw e.Error" hidden?
How to fix it so that ProtocolProcessorMacro catch block will catch the exception. Thx!
public class ProtocolProcessor
{
public void Execute()
{
try
{
// Raise (and log) the Macro Started event
MarkMacroStarted();
// a lot instrument control sequence actions
if ( _protocolProcessorParams.PerformPcrMacro )
{
EvaluateMacroStopPoint( "PCR" );
WriteToRunLog( "!! Start Macro - PCR" );
_pcrBackgroundWorker = new AbortableBackgroundWorker();
_pcrBackgroundWorker.WorkerSupportsCancellation = true;
_pcrBackgroundWorker.DoWork += (_, __) => { _pcrMacro.Execute(_pcrBackgroundWorker.Token); };
_pcrBackgroundWorker.RunWorkerCompleted += ( sender, e ) =>
{
// clear the background worker to indicate it done
_pcrBackgroundWorker = null;
if ( e.Cancelled )
{
WriteToRunLog( "!! PCR Aborted " );
}
else
// Exception occurred
if ( e.Error != null )
{
WriteToRunLog( "!! PCR Exception " + e.Error.Message );
throw e.Error;
}
else
{
WriteToRunLog( "!! Finish Macro - PCR" );
}
};
_pcrBackgroundWorker.RunWorkerAsync();
}
if ( _protocolProcessorParams.PerformTransferPcrMacro )
{
_transferPcrMacro.Execute(token);
}
.......
EvaluateMacroStopPoint( "Macro Finished" );
}
catch( Exception ex )
{
WriteToRunLog( "!!! Exception Occurred in Macro !!! - " + ex.Message );
stoppedByError = true;
throw;
}
finally
{
// Thread.Sleep(200); //is it safe to sleep in finally block?
// handle case where the macro was stopped by the user (not aborted)
// exception occurred, was logged and thrown again
TurnOffAllHeatersAndStopLogging(); //include write sth into run log
}
}
}
private AbortableBackgroundWorker _protocolProcessorBackgroundWorker = null;
private ProtocolProcessor _protocolProcessorMacro = null;
Public void BeginXXXRun()
{
InstrumentControl.Instance.ExceptionThrown += OnInstrumentControlExceptionThrownDuringProtocol;
_protocolProcessorBackgroundWorker = new AbortableBackgroundWorker();
_protocolProcessorBackgroundWorker.WorkerSupportsCancellation = true;
_protocolProcessorBackgroundWorker.DoWork += (_, __) =>
{
try
{
_protocolProcessorMacro = new ProtocolProcessor( );
_protocolProcessorMacro.ProtocolProcessorRunEvent += OnProtocolProcessorRunEvent;
_protocolProcessorMacro.PreExecute();
_protocolProcessorMacro.Execute();
_protocolProcessorMacro.PostExecute();
}
catch ( ThreadAbortException /* taEx */ )
{
}
catch ( Exception ex )
{
GenerateInstrumentExceptionWarningOrFault( ex );
throw;
}
finally
{
_protocolProcessorMacro.StopLoggingToFile();
}
};
_protocolProcessorBackgroundWorker.RunWorkerCompleted += OnProtocolProcessorRunComplete;
_protocolProcessorBackgroundWorker.RunWorkerAsync();
}
}
}