I have a background worker that will throw an exception when there is a problem. I'm trying to catch the exception in the workcompleted event.
My code is roughly as follows:
void workerProcessReports_DoWork(object sender, DoWorkEventArgs e)
{
try
{
//Work is here. The code here throws an exception
}
catch (Exception ex)
{
throw ex;
}
}
void workerProcessReports_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show("There was a problem");
}
else
{
MessageBox.Show("No Problems");
}
}
The problem is that visual studio breaks on the throw ex in the dowork method with the Message
InvalidOperationException was unhandled by user code
What's going on?
Don't catch and rethrow your same exception, that's a waste and causes your stack trace to get messed up.
If you want the exact same exception to be thrown after catching it from a parent exception type, just write throw; in your catch block. If you plan on just throwing everything anyway, don't bother catching it in the first place.
If you do allow your exception to occur without handling it in the doWork method, then you can throw on the parent thread in your RunWorkerCompleted method.
Within your RunWorkerCompleted method you can throw it as such:
if(e.Error != null)
{
throw e.Error;
}
However, at this point if it's something you can handle you may just want to recover and continue, instead of throwing since you are already aware that an exception occured. Especially, if this parent thread is your UI thread, then this is the perfect opportunity to display an error message instead of throwing and potentially crashing your application for a non-fatal error.
Related
I have the following C# code to start camera feed with pressing of button:
private void bntStart_Click(object sender, EventArgs e)
{
webcam.Start();
}
In case that the computer doesn't have a camera installed i get auto MSG error:
"an error occured while capturing the video image. The video capture will now be termenated. Object refrence not set to an istance of object"
My goal is to add my own error msg for the user. I tried the following :
private void bntStart_Click(object sender, EventArgs e)
{
try
{
webcam.Start();
}
catch (NullReferenceException exception)
{
MessageBox.Show(exception.Message);
return;
}
}
but nothing happend. any ideas? I tried to debug but on run time it never gets to the catch... maybe wrong exception?
You are assuming webcam.Start() throws a NullReferenceException, which i believe is not the case, you can try to catch the Exception (it's the base exception, but generally not a good practice), inspect the exception type while debugging and catch the actual exception and do what is required
private void bntStart_Click(object sender, EventArgs e)
{
try
{
webcam.Start();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
return;
}
}
The Exception isn't catched, since it probably isn't a NullReferenceException, so that could mean webcam isn't equal to null.
You could try catching the error using Exception, change your code like this:
private void bntStart_Click(object sender, EventArgs e)
{
try
{
webcam.Start();
}
catch (Exception ex)
{
MessageBox.Show(String.Format("Something went wrong: {0}", ex.Message));
return; //Why is this return keyword here?
}
}
Why do you have return keyword in your code, while the method is at it's end already? Is this code made simple for posting here? I think it can be removed if so. Has nothing to do with your question tough.
It is possible to check for a NullReferenceException and an Exception, do this with following code:
private void bntStart_Click(object sender, EventArgs e)
{
try
{
webcam.Start();
}
catch(NullReferenceException nex)
{
MessageBox.Show(String.Format("NullReferenceException has been catched: {0}", ex.Message));
}
catch (Exception ex)
{
MessageBox.Show(String.Format("Something went wrong: {0}", ex.Message));
return; //Why is this return keyword here?
}
}
Is an exception even being thrown? You said you get an error message, but it's not clear from your description that this is actually an exception rather than the webcam library putting up its own messagebox.
If they're handling the error internally themselves and displaying a messagebox, you're out of luck - you can't catch what isn't being caught.
It seems like the error is caught and handled by the DLL itself. You're out of luck then. If there's no exception being thrown, there's nothing for you to catch. Unless you get access to the source code of the DLL, you're out of luck.
I sometimes get an Exception that my BackgroundWorker is already running after checking it's state with the IsBusy method.
Code:
if(!_worker.IsBusy)
_worker.RunWorkerAsync(stateObj); //<-- exception is thrown here
I don't ever call the worker from anywhere else, so I'm stumped on how to handle this. Should I just ignore it? Or have it call itself?
(e.g.)
void CallWorker(object stateObj)
{
try
{
if(!_worker.IsBusy)
_worker.RunWorkerAsync(stateObj);
}
catch (Exception e)
{
//ignore OR
//CallWorker(stateObj);
}
}
I want to call a method once by a specified interval (e.g. 3 seconds), but I have problem catching exception within the calling method (e.g. Start) thrown by the called method (timer_Elapsed)
Update
public void Start()
{
Timer timer = new Timer(PingPeriod); //System.Timers
try
{
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
}
catch (Exception ex)
{
//I want to catch exception thrown by timer_Elapsed
}
//Logic here that keeps the method running
}
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
throw new exception("Catch this exception please");
}
Update:
Can anyone please confirm that the start() will NOT catch exception thrown from timer_Elapsed, or when trying to invoke timer_Elapsed if exception occurred.
Is there a better alternative, which can catch exception from a called method or get notified?
Any idea would be very much appreciated!
This just isn't possible, the Elapsed event handler runs later, well after your Start() method has exited. Furthermore, that event has the nasty habit of swallowing all exceptions without any diagnostic.
You'll need to handle exceptions within the event handler. Certainly not easy to do. Do consider using the System.Threading.Timer class instead. At least your program will terminate when the callback throws an exception.
This is not possible because the exception is thrown on a different execution context (thread) from the one that set up the timer.
You should handle any exceptions in your callback method. If you want your logic separated from your exception handling, simply create a separate method.
private void TimerElapsedCallback(object sender, ElapsedEventArgs e)
{
try
{
this.DoSomething();
}
catch (Exception ex)
{
// handle
}
}
private void DoSomething()
{
// logic goes here and can be agnostic of any exceptions it throws, if desired
}
I have the following code:
public Mainform()
{
...
// scheduler
scheduler.DoWork += new System.ComponentModel.DoWorkEventHandler(scheduler_DoWork);
scheduler.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(scheduler_RunWorkerCompleted);
scheduler.WorkerReportsProgress = false;
scheduler.WorkerSupportsCancellation = true;
...
...
scheduler_DoWork(this, null);
scheduler.RunWorkerAsync(1000);
...
}
void scheduler_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
scheduler_Enabled = false;
CustomExceptionHandler eh = new CustomExceptionHandler();
eh.HandleUnhandledException(e.Error, "scheduler");
}
if(scheduler_Enabled)
{
scheduler.RunWorkerAsync(1000);
}
}
void scheduler_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
try
{
try
{
...do some stuff
}
catch(MyException ex)
{
ThreadSafeShowError();
}
finally
{}
...do more stuff
}
finally
{
if (e != null && e.Argument != null)
{
Thread.Sleep((int)e.Argument);
}
}
}
The backgroundworker thread died unexpectedly without any exception being thrown. I did not encounter this problem during development and it seems to be hard to reproduce. I suspected that maybe a cross thread exception was occurring when I am doing work in the scheduler_DoWork. I have tried to explicitly update the UI without checking if InvokeRequired and the thread continues to run without problems in a release build. How can this be? (Cross thread exception should occur) How can I determine what causes the thread to die? Any suggestions on how to figure out what is going wrong or how to debug this issue will be appreciated?
The RunWorkerCompleted event might not be fired on the UI Thread. If it is not, then the thread will end and your scheduler object will be garbage collected, which will make it seem like it just quit with no error. See this post for more details. Here and here are SO posts about this.
Your sample doesn't show enough code to determine what's going on but:
Maybe an exception is being thrown from ThreadSafeShowError? Why are you trying to show an error from the worker thread anyway - the conventional thing to do is to show e.Error if not null in the RunWorkerCompleted event handler.
To debug the issue try putting the following around all the code in your DoWork handler:
try
{
// do work
// log a trace statement here
}
catch(Exception ex)
{
// log exception, e.g. with System.Diagnostics.Debug.Write
throw;
}
finally
{
// log a trace statement here
}
You can do several things to increase the possibility of catching the exception:
Enable Managed Debugging Assistants for all exceptions in VS. To do that, go to Debug menu -> Exceptions..., and put a check mark next to "Managed Debugging Assistants" to enable all exceptions to be caught using debugger. Also, depending on the code you are executing, expand the CLR Exceptions node and select nodes of interest ("System" node, for example, will catch all exceptions from the System namespace in the debugger).
Obviously, put a try/catch block around your code, with some logging. You can also do something like this, if you are in real trouble:
try
{
// do stuff
}
catch (Exception ex)
{
#if DEBUG
// break only in DEBUG builds
System.Diagnostics.Debugger.Break();
#endif
// log the exception and throw
throw;
}
Put a try/catch with logging around your Application.Run(...) code in the Main() method. Exceptions do propagate up there sometimes, and this can catch them (even if not coming from this specific part of your code).
Add an Application.ThreadException event handler in your Main() method, before calling Application.Run, like this:
Application.ThreadException +=
new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
In Mainform, you never call scheduler.RunWorkerAsync, so your BackgroundWorker does not start at all.
I have a background worker which can be cancelled.
The normal flows interrupt itself when the CancelPending variable turns to true (responding to user interaction on UI which call worker.CancelAsynch() ), exceptions are thrown because if that (since normal flow is interrupted, lots of null ref exception are thrown)
So when the worker returns, I want to be able to distinguish exception that have been thrown when the worker
was canceled (to silently ignore them) from exceptions thrown when worker was not canceled (to report them to UI).
My code is as follow (sorry for the c#/vb mix ...) :
The worker class:
Public Class ClassBaseGetObjectsWorker
Inherits System.ComponentModel.BackgroundWorker
Protected Overrides Sub OnDoWork(ByVal e As System.ComponentModel.DoWorkEventArgs)
Try
Dim cpt As Int16 = 0
While cpt < 5
System.Threading.Thread.Sleep(1000)
cpt = cpt + 1
If CheckForCancellation() Then
'Simulating exception due to cancel
Throw New Exception("Exception du to cancel !")
End If
End While
Catch exc As Exception
e.Cancel = Me.CancellationPending
Throw exc
End Try
End Sub
End Class
The call back:
void setObjSetCollWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
if (e.Cancelled) {
resultLabel.Text += "Canceled";
//e.Error is selently ignored
}
else {
if (e.Error != null) {
//Reporting errors arising during normal (uncanceled) flow
throw e.Error.InnerException;
}
else {
//Worker process finished without error or being canceled.
updateUIAfterBackgroundJob();
}
}
}
Then, when I'm doing worker.CancelAsynch(), e.Cancelled is set to false (which is not what I expected) in the Completed call back. If I comment out "Trow exc" in the worker, if I test again, e.Cancelled is correctly set to true.
What is the cleanest way to get the information I want, that is: I want to know if the exception popping out in the completed handler was thrown when the worker was in the cancellationPending state or not?
If the best way to structure the code in your OnDoWork()-implementation is to throw an exception when you detect cancellation, do the following:
Create a CancelException:
public class CancelException: Exception {}
Throw this CancelException when you detect that cancellation is pending:
if(CheckForCancellation()) throw new CancelException();
Add a try-catch around the code in your OnDoWork()-method:
protected override void OnDoWork(DoWorkEventArgs e){
try{
//...
}
catch(CancelException){
// silently return
return;
}
}
That way your code will obey the BackgroundWorker-contract (which is to return from OnDoWork() when you detect cancellation pending, rather than to throw an exception), and the Cancelled property should now be as you expect