Preventing unhandled exceptions to stop application - wpf

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.

Related

Win App using Background worker process running on Terminal Server goes Non responsive

There is a Win app tool(C#) running at terminal server which is used to download mails, process the attachment in it and update its UI. Downloading and processing of mail attachments is done using the Background Worker process which also responsible for updating the UI with mails and attachments total and processed count at that instance. There is a timer which ticks to re-initializes the same background worker process after specified duration and look for new mails.
All works fine till the time I am logged in RDC, but when I lock the system (Window key+L) or switch users and comeback to regain the same session the tool is stuck/non responsive, it happens even if I lock and unlock the system instantaneously. I used another process monitoring tool which initially showed child threads getting created and exited periodically but after it is stuck no activity is shown.
I have no clue why is it happening, is window messing is stopped or UI Controls handle are lost or or or....
Following are the chunks of code I am using:
private void tmrScheduler_Tick(object sender, EventArgs e)
{
Application.DoEvents();
if (bgwMailParser == null || (!bgwMailParser.IsBusy && !objfeMailImportNParse.Is_Parsing))
{
bgwMailParser = new BackgroundWorker();
bgwMailParser.DoWork += new DoWorkEventHandler(objfeMailImportNParse.opLoadCommonData);
bgwMailParser.DoWork += new DoWorkEventHandler(objfeMailImportNParse.StartMailImport);
if (HireCraft.Properties.Settings.Default.Close_App_After_Parsing)
bgwMailParser.RunWorkerCompleted += new RunWorkerCompletedEventHandler(opCloseApplication);
bgwMailParser.RunWorkerCompleted += new RunWorkerCompletedEventHandler(opDisposeWorker);
bgwMailParser.RunWorkerAsync();
}
Application.DoEvents();
}
below method handles the events raised by bgWorker process
private delegate void Del_updateParsedCounter(Int64 del_MailCount, Int64 del_AttchCount);
private void UpdateParsedCounter(Int64 MailCount, Int64 AttchCount)
{
try
{
if (lblMailParsedCount.InvokeRequired)
{
Del_updateParsedCounter objUpdateParsedCounter = new Del_updateParsedCounter(UpdateParsedCounter);
this.Invoke(objUpdateParsedCounter, new object[] { MailCount, AttchCount });
}
else
{
lblMailParsedCount.Text = MailCount.ToString();
lblAttchSavedCount.Text = AttchCount.ToString();
}
}
catch (Exception ex)
{
Debug.Assert(false, ex.Message, ex.StackTrace);
}
}
I identified solution to issue but forgot that I raised a question here which wasn't answered.
Well issue was the background worker thread declaring a UIControl deep down somewhere in the code.
When a thread creates a UIControl it also registers itself with SystemEvents.UserPreferenceChanged event which notifies color, theme, screen size changes, system lock/unlock etc. and to respond to which parent thread requires a message pump lacking in background worker thread, the event invoke waits for a (never coming) response causing the application to hang or act non-responsive.
http://support.microsoft.com/kb/943139 link to Microsoft support explains the same.

OutOfMemoryException while bulk data processing with WCF RIA & WF4

I have an existing Silverlight 5 application. I'm adding a page to it to allow users to process mass updates to data in a 3rd party database system. The application currently uses WCF RIA services to communicate to the 3rd party system via SOAP. The functionality of the update is contained in a Workflow 4 application I created and is referenced as an assembly on the server-side of the SL application. Lastly, the application is hosted right now in my local instance of IIS 7.5 running on Windows 7; I'm also debugging with IIS, not the VS dev server.
At the basic level, the application functions as follows:
Select text file
Click "Start" button
Event handler creates an instance of a user-defined Type that keeps track of the batch
Event handler creates a new BackgroundWorker instance and wires up handlers for the DoWork, ProgressChanged, and RunWorkerCompleted events
Event handler calls RunWorkerAsync()
Here's the shortened code for the DoWork event handler, since that's where the majority of the work is done.
private void BwOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs, BatchContainerControl batchProcess)
{
var worker = sender as BackgroundWorker;
// Iterate through each record of data file and call the 'UpdateAddress' function
// of the AddressDomainService which, in turn, executes the Workflow
foreach (var item in batchProcess.FileData)
{
// Check if operation has been cancelled
if (worker.CancellationPending)
{
doWorkEventArgs.Cancel = true;
break;
}
. . .
// Invoke THINKComm.CustomerAddressUpdate Workflow via AddressContext
var invokeOp = _addressDomainContext.UpdateAddress(activityData);
// 'activityData' is an instance of Dictionary<string, string>
invokeOp.Completed += (o, args) => InvokeOpOnCompleted(o, args, batchProcess);
}
}
The handlers for the ProgressChanged and RunWorkerCompleted events, as well as the Completed event of the InvokeOperation instance all, for the most part, update a part of the UI. If you think posting any of that code would be helpful, I'd be happy to update the post.
Speaking of UI, the parts that are updated by the event handlers are two ProgressBar controls - one that tracks the records as they're read from the file and a second one that tracks the records as the update has taken place on the 3rd party database.
Getting to the actual problem...
I've processed files of 10, 100, and 1,000 records with no problem. I then attempted to process a complete file containing ~15,000 records (or 1,907KB of data). The process starts and I can see in the debugger output that the Workflow is being executed. About a quarter of the way through or so, I get an OutOfMemoryException. Here's the stack trace:
at System.ServiceModel.DomainServices.Client.WebDomainClient`1.BeginInvokeCore(InvokeArgs invokeArgs, AsyncCallback callback, Object userState)
at System.ServiceModel.DomainServices.Client.DomainClient.BeginInvoke(InvokeArgs invokeArgs, AsyncCallback callback, Object userState)
at System.ServiceModel.DomainServices.Client.DomainContext.InvokeOperation(String operationName, Type returnType, IDictionary`2 parameters, Boolean hasSideEffects, Action`1 callback, Object userState)
at THINKImportSystem.Web.Address.AddressDomainContext.UpdateAddress(Dictionary`2 activityData)
at THINKImportSystem.BatchProcessPage.BwOnDoWork(Object sender, DoWorkEventArgs doWorkEventArgs, BatchContainerControl batchProcess)
at THINKImportSystem.BatchProcessPage.<>c__DisplayClass10.<StartButtonClick>b__6(Object s, DoWorkEventArgs args)
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.OnRun(Object argument)
Then, the JIT debugger pops up with an error of Unhandled Error in Silverlight Application Code:4004 with a message of System.ServiceModel.DomainServices.Client.DomainOperationException: Invoke operation 'UpdateAddress' failed. Error HRESULT E_FAIL has been returned from a call to a COM component.
I should mention that, sometimes, I get the JIT debugger first. I see in the Debug output that threads are still exiting, and then about 10 or 20 seconds later, the VS debugger pops up with the out of memory exception.
My best guess is that, objects somewhere (maybe related to the DomainService?) aren't being released and therefore, memory usage is building. From what I understand, IIS places restrictions on the amount of memory an application can use, but I can't tell if that's the case here or not.
I was thinking that, each time a record in the file is processed, the objects related to it's processing would be released and therefore overall memory usage would be pretty low. But obviously I'm not understanding how everything is being executed!
I was also wondering if using the TPL as opposed to BackgroundWorker would make a difference?

Reliably Restart a Single-Instance WPF application

I would like to have my current application close and restart. I have seen many posts on this, however none of these seem to work for me.
I have tried
System.Diagnostics.Process.Start(System.Windows.Application.ResourceAssembly.Location);
System.Windows.Application.Current.Shutdown();
However this only restarts the application once. If I press my 'restart' button again (on the already restarted app), it only closes.
I have also tried launching a new System.Diagnostics.Process and closing the current process, but again this does not restart, it simply closes.
How can I restart my current WPF application?
You could create another application which you start when exiting your app and which in return does start your application again. Kind of like how a patcher would work, only without patching anything. On the plus side you could have a loop in that "restart-application" which checks all running processes for your main application process and only tries to re-start it once it does not appear in the process any longer - and you got the bare bones for a patcher also :) Whilst you do not seem to have a problem with restarting your application due to it still being in the processlist - it is the way I would go for when doing it in a production environment as this gives you the most control IMHO.
Edit:
That part in the button event handler (or wherever you want to restart your app with) of your main app (Process2BRestarted.exe in my case):
private void cmdRestart_Click(object sender, EventArgs e)
{
var info = new ProcessStartInfo();
info.FileName = "ProcessReStarter";
info.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(info);
Application.Exit();
}
This should go into your utility/restarter application (ProcessReStarter.exe over here):
private void MainForm_Load(object sender, EventArgs e)
{
// wait for main application process to end
// really should implement some kind of error-checking/timer here also
while (Process.GetProcessesByName("Process2BRestarted").Count() > 0) { }
// ok, process should not be running any longer, restart it
Process.Start("Process2BRestarted");
// and exit the utility app
Application.Exit();
}
Clicking the restart button will now create a new process ProcessReStarter.exe, which will iterate through the process list of all running processes - checking whether Process2BRestarted is still running. If the process does not appear in the list (any longer) it will now start a new Process2BRestarted.exe process and exit itself.

MessageBox.Show early in App startup causes app to terminate

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?

What's causing my WP7 app to crash?

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.

Resources