I've had a few unexplained crashes happening on both the emulator and the phone itself. Basically when my app crashes I get no dialog box whatsoever and the phone returns to the home screen.
I have the following code to display a MessageBox but this is somehow being bypassed...
// Code to execute if a navigation fails
private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
MessageBox.Show(e.Exception.ToString());
}
// Code to execute on Unhandled Exceptions
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
MessageBox.Show(e.ExceptionObject.ToString());
}
The thought occurred to me that it might be related to memory, since my app deals with a lot of images. But I figure that would still be caught by my unhandled exception code above. Any ideas on how I should track this down would be appreciated.
Keep an eye on your memory usage. An OutOfMemoryException crashes your app without calling the Application_UnhandledException handler.
You can check the current memory usage with some built in methods. I blogged about this a while ago http://kodierer.blogspot.com/2010/09/windows-phone-memory-constraints.html
Here's the basic code you should add:
var timer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(2)};
timer.Tick += (s, e) =>
{
var memuse = (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage");
var maxmem = (long)DeviceExtendedProperties.GetValue("DeviceTotalMemory");
memuse /= 1024 * 1024;
maxmem /= 1024 * 1024;
MyTextBlock.Text = String.Format("Mem usage: {0} / {1} MB", memuse, maxmem);
};
timer.Start();
A few things which have happened to me:
If you're doing things on other threads, then IIRC exceptions on those threads will cause the app to just terminate. You may want to wrap the new thread code in an exception handler which propagates the exception to the UI thread
If your app throws an exception before the first page is loaded, that can cause the app to just die without the appropriate handler being called
If you've got a StackOverflowException, that can't be caught and will just make the app bomb
You may want to add some debug-build-only persistent logging (loaded and displayed within the app itself) to make it easier to work out how far the previous run of the application had got before crashing.
My app crashed in exactly the same way.
I tracked it down to throwing an OutOfMemoryException inside a DispatcherTimer tick handler, though the problem probably occurs elsewhere as well.
However, it is not the case that an OutOfMemoryException always takes down your program. It does not. I tried it in various other handlers, and it was correctly caught.
I've posted a blog entry about lost exceptions here
Could your app be being watchdoged for being unresponsive for too long? Perhaps due to the load time of lots of images and this code being executed on the UI thread.
Related
I have a WPF application that consists of multiple projects that have forms, classes, base classes, etc..
Because of the large code base I want to make sure if an exception does happen I can catch it, notify the user and let the application continue without crashing. I understand the pros and cons to doing this.
In the App.xaml.cs of the application I have:
private void OnApplicationStartup(object sender, StartupEventArgs e)
{
Application.Current.DispatcherUnhandledException += CurrentOnDispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
Dispatcher.UnhandledException += DispatcherOnUnhandledException;
UI.Views.Windows.MainWindow.Show();
}
private void DispatcherOnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs dispatcherUnhandledExceptionEventArgs)
{
MessageBox.Show("TEST 3");
}
private void CurrentDomainOnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
{
MessageBox.Show("TEST 2");
}
private void CurrentOnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs dispatcherUnhandledExceptionEventArgs)
{
MessageBox.Show("TEST 1");
}
If an exception happens anywhere those messages boxes are shown which is great, the problem is right after it shows the message the application still crashes. If I run the application in debug, Visual Studio will jump to the place were the exception happened and if I continue it will then go to the message box.
I think the problem has something to do with that but I am not sure. Is there a way to catch the exception like I am above but at the same time not have the application crash after?
Thank You
EDIT
The exceptions that get through to the UnhandledException section will be things like NullReference, NotSupported or Database Exceptions for the most park. If a "serious" exception gets cought like Stack Overflow I will simple notify the user and kill the app. I still need to find a way to stop the app from crashing on non serious exceptions though.
I think you need to set
dispatcherUnhandledExceptionEventArgs.Handled = true;
What kind of exception is your application catching? Using UnhandledException for exceptions that change state will not work unless you are setting HandleProcessCorruptedStateExceptionsAttribute attribute.
From MSDN documentation:
AppDomain.UnhandledException Event
Starting with the .NET Framework 4, this event is not raised for exceptions that corrupt the state of the process, such as stack overflows or access violations, unless the event handler is security-critical and has the HandleProcessCorruptedStateExceptionsAttribute attribute.
http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx
I have a question about exception handling.
To prevent the "[YourProgram] has stopped working" Windows dialog, I usually catch even unhandled exceptions this way:
In App.xaml.cs:
protected override void OnStartup(StartupEventArgs e)
{
Application.Current.DispatcherUnhandledException += ProcessDispatcherException;
AppDomain.CurrentDomain.UnhandledException += ProcessUnhandledException;
// Blah blah blah... Performs a lot of loading operations...
mainWindow.Show();
}
and then
private void ProcessUnhandledException(object o, UnhandledExceptionEventArgs e)
{
logException("An unhandled exception has been thrown\n"+(e.ExceptionObject as Exception).ToString(), e.ExceptionObject as Exception);
Application.Current.Shutdown();
}
Okay, I don't have the Windows dialog. Now ideally I'd like to prevent this force closing scenario. The application I'm developing here has a startup time which lasts around 1 minute for the lightest users (most of them need to wait 2 or 3 minutes for launching it, it has to load a very large and complex data referential), so restarting it can cause trouble
I'd like to know about your "best practices" for this case. I am thinking about just re-creating a new window in the handler and re-show it anyway, so only the UI will be reinitialized to startup state, no other referential will be loaded, 2 - 3 minutes saved. Any other advices?
Oh and of course, this is the "extreme emergency case which should not be reached", but unfortunately it is, mostly due to our dependencies to other systems managed by other branches of the company with who I don't have any control or right to complain (yes, international companies can suck sometime), and it is not try/catchable in code :(
Thanks!
I am assuming from what you are writing that you want your application to be mission critical, meaning, if anything occurs that makes it fail, it needs to be restarted automatically.
The best way to accomplish this is to create a second watchdog process that will restart your application anytime it fails. You can then allow your application to quietly terminate itself when there is an unhandled exception, cleaning up whatever you can in your unhandled exception processor.
The simplest way to implement a watchdog like this is to have a no-window process (e.g., a console app) with a background thread loop that periodically checks that your application is running by checking if a wait handle is locked. Something like this:
// Declared in class
object checkLocker = new object();
bool mtStopCheck = false;
// Thread loop
bool stopCheck = false;
while (stopCheck == false)
{
if (wait_handle_is_unlocked)
restart_application();
Thread.Sleep(1000);
lock (checkLocker)
{
stopCheck = mtStopCheck;
}
}
When you want to shut the watchdog down another thread does this:
// Stop the watchdog thread so the watchdog app can shut down
lock (checkLocker)
{
mtStopCheck = true;
}
Since you'd be running in the same terminal session you don't need a global wait handle so no privilege issues on Vista/Windows 7.
If the user closes the application and you don't want it running again, you can send a signal to the watchdog process (e.g., with named pipes, or use a second kind of wait handle that you lock when you want the watchdog to suspend or shut down) that the app has been shut down and should not be restarted.
You can launch your watchdog in the startup folder or some other automatic method, or, you can have your app launch it the first time it runs.
As part of my App's startup procedure, it checks data integrity, and if it finds a problem it pops up a message to the user telling them that it might take a while to repair things.
I'm showing the message using MessageBox.Show. Because the data check is done from a worker thread, I'm switching over to the UI thread to make that call, and then setting a ManualResetEvent to tell the worker thread when the user has acknowledged the message.
I kick off the data check/load very early in the app's lifecycle from the constructor in the main Application class, by spinning off a worker thread (using the ThreadPool).
When I run with the debugger, and the message is displayed, the app just waits for input. When I run without the debugger, the app terminates after displaying the dialog for 10 seconds.
That 10 seconds is a big clue - it tells me that the OS thinks the app took too long to initialize (the OS kills apps that take too long to start up).
I think that my MessageBox.Show is blocking the UI thread before the App.RootFrameNavigating has a chance to be invoked.
My questions:
Does my diagnosis sound right?
I'd prefer to kick off my data load early, because it is almost entirely IO, except for this Message Box, and the sooner I can get my Model loaded, the better, but do you normally delay your data load until later in the app lifecycle?
Any other ideas/suggestions? I can't guarantee which page will be the start page, because the app could be resuming to any page. I'm also thinking of having the MessageBox.Show delay itself until the app has initialized, perhaps polling away for a flag set by App.RootFrameNavigating - does that make sense?
I think your problem is a result of kicking off the worker thread in the Application constructor. You should use the appropriate life-cycle event, in this case: PhoneApplicationService.Activated Event
So, the solution I've come up with is to still kick off the data load in a worker-thread from the Application's constructor, but in my PhoneService's class ShowDialog method that I invoke to invoke MessageBox.Show, I check to see if the initial navigation has occurred:
private readonly ManualResetEvent _appInitialized = new ManualResetEvent(false);
public void AppInitialized()
{
_appInitialized.Set();
}
public void ShowDialog(string caption, string text, Action<MessageBoxResult> callback, MessageBoxButton button = MessageBoxButton.OKCancel)
{
_appInitialized.WaitOne();
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
var result = MessageBox.Show(text, caption, button);
if (callback != null)
{
callback(result);
}
});
}
Then in my Application class:
private bool _firstNavigate = true;
private void RootFrameNavigating(object sender, NavigatingCancelEventArgs e)
{
if (_firstNavigate)
{
_firstNavigate = false;
var navigationService = (NavigationService) sender;
navigationService.Navigated += NavigationServiceNavigated;
}
....
private void NavigationServiceNavigated(object sender, NavigationEventArgs e)
{
var navigationService = (NavigationService)sender;
navigationService.Navigated -= NavigationServiceNavigated;
PhoneServices.Current.AppInitialized();
}
Anyone see any issues with this approach? Anyone come up with a better way?
Our app crashes during loading probably, only on some machines, I do not get any exception, only the windows "Send report" dialog.
Is there some way to get more information about what is causing the application to crash?
In the "Send report" dialog, there is just:
AppName: evox.wpfclient.exe
AppVer: 1.0.0.0
ModName: kernel32.dll
ModVer: 5.1.2600.5781
Offset: 00012afb
Handle the AppDomain.CurrentDomain.UnhandledException event in your class that starts up your app. Usually program.cs.
Add
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
then outside the main class
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is Exception)
_logger.FatalException("Unhandled exception", (Exception)e.ExceptionObject);
else
_logger.Fatal("Unhandled exception: {0}", e.ExceptionObject);
if (_program != null)
_program.Exit();
}
to the startup file and see if it catches your exception. of course change the method to suit your purposes.
The first thing you do when your application launches, try subscribing to the event System.AppDomain.CurrentDomain.UnhandledException. In the event handler, you can log the exception before the application actually crashes.
If your application still crashes without logging, it's probably a problem with the .NET framework. In that case, you should see an event in the Windows Administration Tools Event Viewer.
Note: you should only use the UnhandledException event to log and then crash - don't try to recover and continue executing.
Is this a bug in Winforms? (tested on both VS2008 and VS2010)
private void Form1_Load(object sender, EventArgs e)
{
throw new Exception("Hey");
}
I don't receive any error in that code, awhile ago, I'm trying to formulate a solution for this question Parse a number from a string with non-digits in between
And I do this code in Form1_Load:
private void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("X");
string s = "12ACD";
string t = s.ToCharArray().TakeWhile(c => char.IsDigit(c)).ToArray().ToString();
MessageBox.Show("Y");
int n = int.Parse(t);
MessageBox.Show(n.ToString());
}
I wonder why it didn't show the number. Then on moving the code to button1_Click...
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("X");
string s = "12ACD";
string t = s.ToCharArray().TakeWhile(c => char.IsDigit(c)).ToArray().ToString();
MessageBox.Show("Y");
int n = int.Parse(t);
MessageBox.Show(n.ToString());
}
...then I noticed that there's an error: Input string was not in a correct format.
Why Form1_Load didn't catch any exception, why it silently fail? The code just exit out of form1_load at string t = s.ToCharArray().TakeWhile...
Rewrite, I've since figured out where it comes from. Windows misbehaves when an exception is raised in a 32-bit process when it runs on a 64-bit version of Windows 7. It swallows any exception raised by code that runs in response to a Windows message that's triggered by the 64-bit windows manager. Like WM_SHOWWINDOW, the message that causes the Load event to get raised.
The debugger plays a role because when it is active, normal exception trapping in a Winforms app is turned off to allow the debugger to stop on an exception. That doesn't happen in this scenario because Windows 7 swallows the exception first, preventing the debugger from seeing it.
I've written about this problem more extensively in this answer, along with possible workarounds.
See this: The case of the disappearing OnLoad exception. It's by-design (though by-extremely-stupid-design, IMO). Your exception is hitting a kernel-mode boundary during the unwinding of the stack. If you can, switch to some other event, or don't let exceptions escape; this doesn't help if you're expecting your debugger to automatically break on an un-handled exception in OnLoad.
If you care, I wrote a bit more in this answer.
The WinForms framework classes won't automatically catch any exceptions for you. That isn't a bug, it's by design - what would they do with the exception?
You have to have your own try/catch block in any event or alternatively handle the Application.ThreadException event. That event can be helpful for some generic handling code like logging the exception or displaying an error dialog, but obviously it can't do anything specific to any individual event or exception type.