I got TargetInvocationException while doing long process in another thread caused by a windows control on UI thread (Progress Bar). This exception leads my app to crash (goes to main method in debugging) and could not be caught by try catch. I figured out what made this exception, and fix it (that was trying to assign “Value” property by a value that exceeds the maximum). But it made me wondering how I can catch exception like this (in production code) so I have an option to recover my application instead of terminating the application.
views:
508answers:
4Chances are you aren't going to be able to recover very much. In terms of your operation, the state of a good number of stack frames (and objects referenced from those stack frames) is probably invalid because of the error.
Because of that, at best you can recover at a very high level and try the operation again.
If the resources you are accessing are able to be contained in a transaction, then I would suggest doing that, so that you don't have to worry about inconsistencies in persisted data.
Also, you might want to check out this thread on SO:
http://stackoverflow.com/questions/183589/c-windows-forms-best-practice-exception-handling
As well as the Exception Handling Application block from Microsoft:
Catch the exception and find a mechanism to pass it back to the main or calling code.
You can 'handle' exceptions (really, you're just receiving notification of them) on the GUI thread via the static event Application.UnhandledException
.
When you attach a handler to this event, it will be invoked for all unhandled exceptions on the WinForms UI (message pump) thread. The fact that you have this handler attached means that the Application
won't exit. Without it, WinForms shuts down your application.
Not sure what version of .net you are using if its 3.0+ you can do something along these lines.
private void UpdateValue(int newValue)
{
Action myAction = () => progressBar.Value = newValue;
if (progressBar.InvokeRequired)
progressBar.Invoke(myAction);
else
myAction();
}
Call this method with the new value for the progress bar it will check if the call needs marshalling and make the appropriate call. Be careful InvokeRequired is relatively expensive, so use it only where needed. You could make this into an extension method to make generic use of this pattern for other controls if needed.
Hope this helps.