I'm working on a WinForms project and at one point I have to load a XmlDocument in the background. I have a BackgroundWorker do this, but when the XmlDocument can't be found the BackgroundWorker throws a System.IO.FileNotFoundException in DoWork instead of passing it onto RunWorkerCompleted.
private void LoadBgWorker_DoWork(object sender, DoWorkEventArgs e)
{
//---download manifest---
SetStatusText("Downloading manifest...");
Manifest = new System.Xml.XmlDocument();
Manifest.Load(Properties.Resources.ManifestUrl); // <-- this is where the code gets stuck, it alerts me that the exception is unhandled
}
private void LoadBgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
Success = false;
Error = e.Error;
this.Close();
}
else
{
//---loading complete, close form---
Success = true;
this.Close();
}
}
Am I missing something here? Shouldn't the exception automatically trigger RunWorkerCompleted so it can be handled there?
Did you check if you have the System.IO.FileNotFoundException "Break when thrown" ticked in the Exception Settings ?
It might be it, as backgroundworker DoWork catch an exception if thrown.
From Microsoft (full article here) :
Tell the debugger to break when an exception is thrown
The debugger can break execution at the point where an exception is
thrown, so you may examine the exception before a handler is invoked.
In the Exception Settings window (Debug > Windows > Exception
Settings), expand the node for a category of exceptions, such as
Common Language Runtime Exceptions. Then select the check box for a
specific exception within that category, such as
System.AccessViolationException. You can also select an entire
category of exceptions.
Related
I have no idea, why my program crash.
If i click "Reload" Button:
private void reloadBtn_Click(object sender, RoutedEventArgs e)
{
comboFilter.Items.Clear();
dataGridPrivatecustomers.Columns.Clear();
dataGridPrivatecustomers.ItemsSource = null;
load_columns_privatecustomer();
load_values_privatecustomer();
}
All works.
But if I select a filter for my search function and click reload, then it crashes:
private void comboFilter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
labelfilter.Content = "Filter: " + comboFilter.SelectedItem;
filtervalue = comboFilter.SelectedItem.ToString();
}
This is the breakpoint:
filtervalue = comboFilter.SelectedItem.ToString();
And I get a NulLReferenceException Error.
I tryed to make a filtervalue = null; in reloadBtn_Click but also doesn't work.
The comboFilter_SelectionChanged is somehow fired after the reload where you remove items from the combo, which is result of clear method. Make sure you have SelectedItem not null in comboFilter_SelectionChanged before you use it.
private void comboFilter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if( comboFilter.SelectedItem != null)
{
labelfilter.Content = "Filter: " + comboFilter.SelectedItem;
filtervalue = comboFilter.SelectedItem.ToString();
}
}
As a additional note your program must not crash by not catching the exception being thrown in your program. Use try-catch to properly handle the exception. And also try to avoid them before they could occur. Like we did here by checking for null. This will prevent program crashing.
try-catch (C# Reference) - Why program would crash (stop execution)
When an exception is thrown, the common language runtime (CLR) looks
for the catch statement that handles this exception. If the currently
executing method does not contain such a catch block, the CLR looks at
the method that called the current method, and so on up the call
stack. If no catch block is found, then the CLR displays an unhandled
exception message to the user and stops execution of the program.
The exception gets thrown because comboFilter_SelectionChanged is called implicitly from reloadBtn_Click when comboFilter.Items.Clear() is called. In this case comboFilter.SelectedItem changes from the previously selected item to null.
Check for null in comboFilter_SelectionChanged:
private void comboFilter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (comboFilter.SelectedItem != null)
{
labelfilter.Content = "Filter: " + comboFilter.SelectedItem;
filtervalue = comboFilter.SelectedItem.ToString();
}
}
You may want to add a null-check for comboFilter.SelectedItem, e.g. like comboFilter.SelectedItem?.ToString()
I want a crash reporting, so I register the UnhandledException event in App.xaml.cs like following. But there are 2 problems:
Sometimes, there is no callstacks for exception
Sometimes, I don't have enough time to write log into file before the process is terminated.
Any advice?
this.UnhandledException += App_UnhandledException;
private async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (!hasHandledUnhandledException)
{
e.Handled = true;
_logger.Error("Unhandle exception - message = {0}\n StackTrace = {1}", e.Exception.Message, e.Exception.StackTrace);
await CrashHandler.ReportExceptionAsync(e.Exception.Message, e.Exception.StackTrace);
hasHandledUnhandledException = true;
throw e.Exception;
}
}
Make sure to access e.Exception only once. In some cases, information about the stacktrace is lost the second time you access the property. Save the exception in a variable and work directly with that variable. Also, as mentioned by Panagiotis Kanavos in the comments, directly log e.Exception.ToString() to make sure to miss no information. This will include the message, the callstack, and all inner exceptions (which you are not logging in your current code).
private async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (!hasHandledUnhandledException)
{
e.Handled = true;
var exception = e.Exception;
_logger.Error("Unhandled exception - {0}", exception);
await CrashHandler.ReportExceptionAsync(exception.Message, exception.StackTrace);
hasHandledUnhandledException = true;
throw e.Exception;
}
}
As for the problem of not having enough time to log the exception, it's controlled by the runtime so you can't do anything about it.
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.
we're having an application on server instance and quite rarely, but we have out of memory exception (program is not leaking, just instance is quite small and it operates with quite big amounts of data).
That would be not a problem, as we monitor processes on that server instance and if some of the processes are not found in process list, alert email is sent.
Now the problem is with this:
That prevents process from disappearing from process list, so we don't get alert email about it's failure. Is it possible to disable this message, that if program fails on something we don't catch, it would close without user interaction?
Assuming Windows Forms, I typically do multiple steps to prevent this message box.
First, I connect several handlers in the Main function:
[STAThread]
private static void Main()
{
Application.ThreadException +=
application_ThreadException;
Application.SetUnhandledExceptionMode(
UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException +=
currentDomain_UnhandledException;
Application.Run(new MainForm());
}
Those handlers are being called when an otherwise unhandled exception occurs. I would define them something like:
private static void application_ThreadException(
object sender,
ThreadExceptionEventArgs e)
{
doHandleException(e.Exception);
}
private static void currentDomain_UnhandledException(
object sender,
UnhandledExceptionEventArgs e)
{
doHandleException(e.ExceptionObject as Exception);
}
The actual doHandleException function that is then called does the actual error handling. Usually this is logging the error and notifying the user, giving him the options to continue the application or quit it.
An example from a real-world application looks like:
private static void doHandleException(
Exception e)
{
try
{
Log.Instance.ErrorException(#"Exception.", e);
}
catch (Exception x)
{
Trace.WriteLine(string.Format(
#"Error during exception logging: '{0}'.", x.Message));
}
var form = Form.ActiveForm;
if (form == null)
{
MessageBox.Show(buildMessage(e),
"MyApp", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
MessageBox.Show(form, buildMessage(e),
"MyApp", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
With the helper function:
public static string buildMessage(Exception exception)
{
var result = new StringBuilder();
while (exception != null)
{
result.AppendLine(exception.Message);
result.AppendLine();
exception = exception.InnerException;
}
return result.ToString().Trim();
}
If you are using not Windows Forms but e.g. a Console application or WPF, some handlers are not present, while others are present instead.
The idea stays the same: Subscribe to event handlers that are being called if you have no try...catch around your code blocks.
Personally, I try to have as few of those try...catch blocks as possible (ideally none).
don't know if you can deactivate this - but I think you should not.
Find the bug/problem in your application and handle the problem with a craceful shutdown or by preventing the problem in first case.
Everything else will be a real crude workaround and I don't think your client will be pleased to have such a behavior (after all won't there be data lost? If not this has allways the buggy / not finished touch)
You could put a global try/catch block in your program and exit the program on any unexpected exception.
If using WPF you can try-catch the following two exceptions in your app.xaml.cs. There may be other/complementary exceptions to handle, but this are the two I am usually looking for:
AppDomain.CurrentDomain.UnhandledException - "This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application. If sufficient information about the state of the application is available, other actions may be undertaken — such as saving program data for later recovery. Caution is advised, because program data can become corrupted when exceptions are not handled."
Dispatcher.UnhandledException - "Occurs when a thread exception is thrown and uncaught during execution of a delegate by way of Invoke or BeginInvoke."
ie:
public partial class App : Application
{
public App()
{
this.Dispatcher.UnhandledException += DispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;
}
private void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// log and close gracefully
}
private new void DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
// log and close gracefully
}
}
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.