.NET Forum / Languages / C# / March 2008
How to force the program to continue after unhandled exception detection
|
|
Thread rating:  |
nano2k - 07 Mar 2008 22:11 GMT Hi
For my winforms app (.net 2.0) I have defined a general exception handler:
Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
//....
void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) { //show a decent message }
Ok, the thing is that when in debugging mode and an unhandled exception occurs, the exception helper pops up. On this point, I'm stucked. Can't get rid of exception helper, even if I want the exception to be handled by the general exception handler I defined. I have played with exception settings (CTRL-D, E), but no luck. I really need to keep this design, so I need to be able to let the program to continue execution. How to do this?
Thanks.
Peter Duniho - 08 Mar 2008 00:07 GMT > [...] > On this point, I'm stucked. Can't get rid of exception helper, even if > I want the exception to be handled by the general exception handler I > defined. There's a fundamental mistake in your assumptions. That is, you have not actually defined a "general exception handler".
You've defined a handler for the ThreadException _event_, but that's entirely different. It doesn't handle an exception, it handles the event that's raised when an exception _isn't_ handled.
If you want the exception to be handled, you need to handle it. With a try/catch block, not an event handler.
Pete
nano2k - 08 Mar 2008 08:33 GMT > > [...] > > On this point, I'm stucked. Can't get rid of exception helper, even if [quoted text clipped - 12 lines] > > Pete You're right, I made a mistake. I handled an event, that's right. But the question remains. I want to get rid of exception helper and let this event handler deal with the exception. I have tons of places where exception handling is necessary and the handler looks like: "If an unhadled exception raises, than simply display its message and continue running!". Why should I write _the same_ code each time? Of course, there are also many many cases where I need to handle specific types of exceptions and take the appropriate measures. I'm not talking about these ones. But in modern exception handling approach, implementing a general exception catching mechanism is a _must_. The only problem is that I get stucked in VSNET2005 when such an "unhandled" exception occurs.
Jeroen - 08 Mar 2008 08:40 GMT Nano2k,
Press 'Continue' (a green arrow button pointing rightward, from the top of my had) in the Visual Studio debugger, and then the code will go into your event handler when running from Visual Studio as well.
Let us know if that solved your problem.
Regards, Jeroen
nano2k - 08 Mar 2008 09:24 GMT > Nano2k, > [quoted text clipped - 6 lines] > Regards, > Jeroen Sorry, doesn't work...
Peter Bromberg [C# MVP] - 08 Mar 2008 17:46 GMT I believe the issue you may be running into here is the default behavior of .NET 2.0 and beyond regarding unhandled exceptions. If there is an unhandled exception, the appDomain promptly unloads and that is the end of the picture. You can override this behavior, but in general that's not a good idea. -- Peter Site: http://www.eggheadcafe.com UnBlog: http://petesbloggerama.blogspot.com Short Urls & more: http://ittyurl.net
> > Nano2k, > > [quoted text clipped - 8 lines] > > Sorry, doesn't work... Peter Duniho - 08 Mar 2008 18:00 GMT >> Press 'Continue' (a green arrow button pointing rightward, from the >> top of my had) in the Visual Studio debugger, and then the code will [quoted text clipped - 3 lines] > > Sorry, doesn't work... What doesn't work about that? Are you saying that even when you've subscribed to the ThreadException event, that when an exception occurs your application cannot be continued?
If not, then what are you saying?
And in either case, especially because of the apparent confusion in what you're trying to describe, it would be very helpful if you would provide a concise-but-complete code example that demonstrates the problem. Describe very clearly what it is you expect to be able to do with the example, and what you observe it doing instead.
Pete
Peter Duniho - 08 Mar 2008 17:45 GMT > You're right, I made a mistake. I handled an event, that's right. > But the question remains. I want to get rid of exception helper and > let this event handler deal with the exception. While I don't know what an "exception helper" is, and "deal with" is ambiguous. But assuming you mean for the event handler to actually trap the exception, the short answer is that you can't do that. It doesn't trap exceptions. It's entirely unrelated to the exception except that it gets raised by the .NET exception handler when an exception is thrown in the main GUI thread.
It's not an exception handler, and it will never be one.
> I have tons of places where exception handling is necessary and the > handler looks like: "If an unhadled exception raises, than simply > display its message and continue running!". Why should I write _the > same_ code each time? Because you want to handle the exception?
> Of course, there are also many many cases where I need to handle > specific types of exceptions and take the appropriate measures. I'm > not talking about these ones. > But in modern exception handling approach, implementing a general > exception catching mechanism is a _must_. Well, obviously it's not a "must" since plenty of modern frameworks that use exceptions don't provide a way to implement a general catching mechanism.
> The only problem is that I get stucked in VSNET2005 when such an > "unhandled" exception occurs. I'm not aware of any setting in VS2005 that will allow the debugger to ignore exceptions that would be handled by the .NET GUI thread exception handler. That doesn't mean the setting doesn't exist, it just means I don't know where it is if it does.
Regardless, it's not a good idea for you to have a dependency on this general purpose exception handling. Exceptions are exceptional cases. If they are being thrown regularly enough that you find it overly time-consuming to add exception handlers everywhere that they could come up, then either your code is throwing too many exceptions or you are not handling them in the way that you should.
An exception represents an error. Either you have a good way to recover from an error or you don't. If you do, then the exception handler that will allow you to recover from an error belongs with the code where the error is created. That means writing exception handling code (i.e. using try/catch). If you don't have a good way to recover from an error, then no matter where you put whatever code reacts to the error, it's still wrong.
I'm sorry your frustrated by this, but I believe that if what you're trying to do was a good way to design a program, you wouldn't be fighting the tools trying to do it.
Pete
Peter Duniho - 08 Mar 2008 18:50 GMT > [...] >> The only problem is that I get stucked in VSNET2005 when such an [quoted text clipped - 4 lines] > handler. That doesn't mean the setting doesn't exist, it just means I > don't know where it is if it does. I take that back. A few minutes of looking revealed to me that in the Debug/Exceptions... menu, if you uncheck the "User-unhandled" column for an exception, then as long as that exception is handled _somewhere_ (for example, in the Application class's default exception handler, which is active when you subscribe to the ThreadException event), the debugger won't interrupt the program.
I still assert that if your application is dependent on this sort of thing, there's something wrong with the design, and I also don't understand why you aren't able to continue after the exception when it's being handled (that works fine for me). But it appears to me that you can get VS to do exactly what you want, however inappropriate it might be to do so.
Pete
nano2k - 10 Mar 2008 17:22 GMT Hi Peter.
Let's say my client app calls a webservice. The webservice is pretty much used by the client app. That is, the application performs many accesses to the webservice because it maintains a database behind the webservice. For this, the webservice implements many different methods callable from the client app. Now, it's not hard to imagine that each webservice call _could_ fail because of network failures, etc. BUT, the message will still be the same. Like: "Oops, the call failed!" or: "Unexpected error". It is a huge and unnecessary work for me to handle each webservice call by copy/pasting the same code to handle the exceptions. Not to mention what happens if I want to change the error message to: "Oh my God! An unexpected error!". Or if you want to translate the message... Well, getting serious now. Such a general error handling system is very useful in these situations. Note: I understand that the handler is only an _event_ handler, not an _exception_ handler. All this talking is to make you understand that handling _each_ potential exception could be itself a design problem leading at least to inconsistency in treating unexpected exceptions. To put it in another way, handling _all_ possible exception types that might raise from each piece of code could rather be a design problem in some situations. Not in all situations. But some of them.
Now, if I put my trust in handling Application.ThreadException event, even if it works flawlessly, VS Studio 2005 will always pop-up the exception helper window (this is good and normal), but the bad thing is that this exception helper won't go away no matter what I try. An also, the execution pointer will not advance. It detects an unhandled exception, which, yeah!, it's true!, ignoring that the exception is, or coudl be, somehow, handled in the handler associated with the Application.ThreadException event.
Running the application without attaching the debugger (e.g. CTRL-F5), all works fine. The exception is raised, but the general error message appears gracefully. I can dismiss the message and the application is perfectly recovered.
Now, a little bity of code: I have a base form and a bunch of forms derived from this base form. All these forms work inside a MDI Parent form as MDI childs. ONLY ONE MDI child is shown at a time. Each time a new form is shown (based on user selection through a menu), the current form is closed and disposed. Then, the new one is created and shown. The base form looks like this:
public class BaseForm : Form { public BaseForm() { Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); } //...few different members... protected override void OnClosed(EventArgs e) { Application.ThreadException -= new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); base.OnClosed(e); } void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) { Utils.ShowGeneralErrorMessage(this, e.Exception); } }
Now, let's imagine we have a form that is derived from BaseForm and has several buttons. Each button produces one or more webservice methods invocations:
public partial class FirstForm : BaseForm { private void button1_Click(object sender, EventArgs e) { //some code //followed by webservice call(s) } private void button2_Click(...) { //simmilar to button1 }
//other buttons PLUS other calls to the webservice
}
Now, why should I "decorate" each code in Click event handlers with something like this?:
private void button1_Click(object sender, EventArgs e) { try { //call webservice } catch (SoapException ex) { Message.Show(ex.Message); } }
Just because the exception helper won't let me? It could be an answer, but could I disable this behavior? Note: I have already played fair enough with Debug/Exceptions settings. Can't make it work as I expected. I didn't assume I didn't make a design mistake when I expected this behavior. But how could I solve this issue?
Thanks again.
> On Sat, 08 Mar 2008 09:45:03 -0800, Peter Duniho > [quoted text clipped - 23 lines] > > Pete Peter Duniho - 10 Mar 2008 17:50 GMT > [...] > Now, if I put my trust in handling Application.ThreadException event, > even if it works flawlessly, VS Studio 2005 will always pop-up the > exception helper window (this is good and normal), but the bad thing > is that this exception helper won't go away no matter what I try. Then I take it you have not tried the solution I posted in my previous message.
I disagree with your analysis of "why" you need to handle exceptions with the ThreadException event, but the fact is that even doing so it's not difficult at all to get the debugger to ignore exceptions that you've handled that way.
If you are having some trouble getting that technique to work, you should explain better what you're doing and what's not working as you expect.
Pete
nano2k - 11 Mar 2008 16:00 GMT Pete, First of all, thanks for your patience. You may repro the behavior with VSNET 2005 like this: 1. Create a winform app. 2. Put a button on the form.
3. Add this handler for form's Load event: private void Form1_Load (object sender, EventArgs e) { Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); } 4. And for FormClosed event: private void Form1_FormClosed (object sender, FormClosedEventArgs e) { Application.ThreadException -= new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); } 5. Then, implement the ThreadException handler like this: void Application_ThreadException (object sender, System.Threading.ThreadExceptionEventArgs e) { MessageBox.Show(e.Exception.Message); //show simple message } 6. Simmulate an unhandled exception: private void button1_Click (object sender, EventArgs e) { //simmulate an unhandled exception throw new ApplicationException("Ooops! Unhandled exception!"); }
7. Normally, if no event handler was defined for Application.ThreadException event, the application would crash when the button is clicked. Run the application without debugger: CTRL-F5. Click the button: the error message appears. Dismiss the message. The application is running normally.
8. Run the application with the debugger attached. Click the button. The debugger detects the unhandled exception and stops the program at the following line showing the exception helper:
throw new ApplicationException("Ooops! Unhandled exception!");
Cool, until now, it's perfect! Now, try to continue the execution of the program. No chance! No matter what settings you change in Debug/ Exceptions section. It is normal to be able to continue the execution, as the application WILL ACTUALLY CONTINUE ITS EXECUTION when running in production environment.
Now, if there's a design problem, I wonder what good is for to handle the Application.ThreadException event (I mean when in debug mode). Anyway, even if it's a design problem (which I don't think), can I make the exception helper let me be?
Thanks.
> > [...] > > Now, if I put my trust in handling Application.ThreadException event, [quoted text clipped - 14 lines] > > Pete Peter Duniho - 11 Mar 2008 18:25 GMT > Pete, > First of all, thanks for your patience. [quoted text clipped - 8 lines] > System.Threading.ThreadExceptionEventHandler(Application_ThreadException); > } From the MSDN documentation for the Application.ThreadException event, in a clearly emphasized "Note:" box:
"To use this event, you must attach a handler before you call Application.Run"
http://msdn2.microsoft.com/en-us/library/system.windows.forms.application.thread exception.aspx
> [...] > 7. Normally, if no event handler was defined for [quoted text clipped - 3 lines] > error message appears. Dismiss the message. The application is running > normally. I'm surprised you even got it to work at all using the code you posted.
> 8. Run the application with the debugger attached. Click the button. > The debugger detects the unhandled exception and stops the program at [quoted text clipped - 5 lines] > the program. No chance! No matter what settings you change in Debug/ > Exceptions section. I am unable to reproduce your problem, at least when I used the ThreadException event correctly. I haven't bothered to try using it wrong, but I can believe that there might be a difference.
When I set up a ThreadException handler correctly, by subscribing the handler before I call Application.Run(), then once the debugger detects the exception and interrupts the program, I can simply continue execution and the program continues running just as it would have had the debugger not been present.
If you can reproduce the problem you're describing when you've used ThreadException correctly, _then_ there's something for you to be concerned with. But in that case, it means that there's something about your installation that is broken.
Normally it would work just as you desire (and as I noted, you can even disable interrupting execution for handled exceptions altogether...the default is for the debugger to break any time an exception isn't handled by your own code, but you can set it for other behaviors, including breaking only when the exception is unhandled altogether, or breaking whether or not the exception is handled anywhere).
Pete
nano2k - 12 Mar 2008 09:03 GMT > > Pete, > > First of all, thanks for your patience. [quoted text clipped - 60 lines] > > Pete Pete, you're the one! Handling the event _before_ calling Application.Run() worked! Indeed, I was using the wrong way this handler. Anyway, maybe this topic will help someone else.
Thanks again.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|