It appears that an asynchronous delegate was an acceptable solution for OP,
but this isn't always the case. There are times when people need to use a
normal thread, rather than an asynchronous delegate.
What do you mean by normal? Do you mean to distinguish between a threadpool
thread and a manually created thread?
A specific exception
may be handled on the thread where code can be wrapped in a try/catch block.
However, it isn't practical to write catch blocks for every possible
exception that can be raised.
The only time where it is not practical is when the exception actually
occurs in code written by 3rd parties over which you have no control and on
threads which are created internally by the 3rd party code. In this case,
the reason why you cannot wrap it in a try-catch is because it is not
possible, not because it is not practical. In all other cases, if the
exception occurs in a thread proc written by yourself you can wrap it in a
try-catch.
You may be thinking that you do not want to catch all exception types within
the scope of a particular catch block. I partially agree with that, but that
is still not the same thing as wrapping all your execution threads in a
try-catch block. A particular subsystem may catch some exceptions but not
all, and that is fine, but the code that invokes it should wrap it in its
own backstop try-catch handler - the buck has to stop somewhere, and it
ought not to be in a UE handler.
I also am unconvinced that not all exception types should be caught - I
prefer to catch-wrap-throw to add context to the exception error message.
The extra performance hit is usually less important then the additional
error information available to users/tech support/developers.
The global exeption handler can serve as a
backup mechanism to keep your program from crashing because of unhandled
exceptions.
This is an incorrect statement. You will definitely NOT keep a program from
terminating. One of the fields (IsTerminating) in the unhandled exception
event argument indicates whether or not the runtime is terminating as a
result of the unhandled exception. This is a readonly field - if it is set
to true then the application will terminate immediately after the unhandled
exception handler has run to completion. The app has no direct control over
this value.
The decision on whether to catch System.Exception may or may
not have anything to do with timing between catch and finally blocks,
depending on the application.
I do not follow the logic in this statement. The specific exception type
caught has nothing to do with the timing between the catch-finally blocks.
past.
I think it depends on the application as to whether this matters or not.
True, but the difference is whether or not the runtime will terminate the
app immediately thereafter - the app has no control over this. Currently the
only way to influence this is by the thread the UE occurs on.
Sure, global exeption handlers are for managed code. The fact that some
unmanaged code might crash the CLR still doesn't convince me that I
shouldn't use a global exception handler.
Threads can originate in unmanage code and make calls that wind up in
managed code (e.g. CCW). If managed code makes a call to unmanaged code and
that code throws an exception, or if it returns an error that the runtime
converts to an exception, then the runtime will propagate that exception
back up the callstack to the managed thread. An unhandled exception handler
is for all exceptions reflected into the managed environment, regardless of
where it originated.
While it is true that a call into unmanaged code can crash the app, it is
not necessarily because of an unhandled exception on a managed thread -
unmanaged code can directly call TerminateProcess and the runtime cannot
guard against that. It could also launch another unmanaged thread, have an
unhandled exception on that thread, and the win32 subsystem can crash the
app. Unmanaged code is code in the wild.
If the exception occurs on the execution thread that calls into unmanaged
code, then if that code throws an exception it can be caught the same as any
other exception.
Why would you not rely on this working consistently across multiple versions
of the runtime? Microsoft explains how this is done through their
architectural guidance document "Exception Management in .NET":
There are inconsistencies and weaknesses in how exception handling is
implemented, and the behavior will probably change. For one thing, you can
only successfully subscribe to the unhandled exception event in the default
appdomain. You can subscribe to it in other appdomains but the handler for
it will never be called, and the subscription attempt itself does not
generate an error to indicate an error. For another, the decision of whether
to terminate the app is based algorithms that are questionable (e.g. why
should it matter which thread the UE occurred on?), and even worse, make it
impossible for an app to fully control an execution environment.
The decision to terminate an app or not should be a policy decision by the
controlling app, and the system should provide reasonable default backstop
behavior. There currently is no way for an app, such as a managed host
setting up a secure execution environment, to set this policy - there ought
to be.
The management guide also is misleading in its description of how a UE is
handled by the runtime. I think it is good guide but not the last word on
the subject. The links I provided go into detail on the mechanics of
exception handling in .net.
I'm very familiar with that link you provided and the information it
provides is incomplete.
Here are a few links you should read...
http://blogs.msdn.com/cbrumme/archive/2003/04/15/51345.aspx
http://blogs.msdn.com/cbrumme/archive/2003/10/01/51524.aspx
http://www.microsoft.com/msj/0197/Exception/Exception.aspx
http://msdn.microsoft.com/library/d...handlingraisingexceptionsinxmlwebservices.asp
http://msdn.microsoft.com/library/d...ml/vbtskhandlingexceptionsinyourcomponent.asp
I'm open minded enough to hear new ideas and if you have information that
would change my mind, then I'm interested in hearing it.
For one, there is a big difference between what are called unhandled
exception handlers and the "raw" unhandled exception handler as implemented
by the runtime. The winform UE handler (and I believe the ASP UE handler as
well) do not appear to actually provide access to the low-level UE. From the
testing I have done the Winform UE seems to wrap the winform itself in a
try-catch (and only on the main thread), and if your own app does not catch
the exception it will catch it and deliver the UE itself to any subscribed
listeners - this prevents the UE from crashing the app because from the
runtime's perspective the exception was handled. If none are subscribed the
exception is allowed to propagate and is treated as a normal UE (I believe
it propagates without actually being caught and rethrown - I suspect it
makes the decision in an exception filter).
The difference between the two can be observed by examining the timing
between when the UE is delivered to subscribed event handlers and when
finally blocks run. The low-level UE event will be delivered after the
runtime has performed the 1st pass of searching for a suitable catch handler
and before finally blocks are run. If none is found it fires the UE event
and then goes back and on the 2nd pass it runs all finally blocks; the
sequence is to 1st search for a catch handler, deliver the UE and then 2nd
run the finally blocks. For winform apps that subscribed to the
Application.ThreadException event, this is delivered after all finally
blocks have run, which is what the behavior would be if it caught the
exception itself and then delivered the event. The sequence here is to 1st
search for a catch handler, then on the 2nd pass to run the finally blocks,
and then to eventually deliver the UE event.
I haven't actually tested the asp.net behavior but I believe it is very
similar to what I've described for the winform. The reason why the app
doesn't crash when subscribed to either is that the runtime library is
handling the exception on your behalf.
Now, if you don't care about the difference that is fine, but one should at
least know that there is a difference.
As far as I can tell there are 3 different UE mechanisms, 1 in the runtime
and 2 in the BCL...
AppDomain.UnhandledException (runtime)
Application.ThreadException (WinForms BCL)
Page.Error and Application_Error (ASP .NET BCL)
The 1st is the runtime's notion of a UE handler.
I believe the other two are provided by the BCL and are layers on top of the
runtime's standard exception handling. If you get a winform or asp.net UE
event then the runtime itself does not see it as a UE. Again, this is based
on my observation - I do not have the actual source code to see how it was
actually done. I suspect those lib's actually use an exception filter to
determine whether to catch the exception and generate the UE event or let it
propagate unhandled.
Right. It could be a problem, i.e. in cases where you caught a specific
exception and want capture some information before disposing a resource.
That is correct. And there is a difference in the timing when a finally
block is run and the UE is delivered depending on whether it is an Appdomain
UE or the Winform or ASP UE. In most cases it does not matter, but sometimes
it might.
However, I don't see that as a reason not to have a global exception
handler.
Then I suppose we shall have to agree to disagree. I believe a UE should be
used for logging/trouble-shooting, etc, but it does not prevent an app from
terminating. For actually dealing with exceptions I believe that
try-catch-finally constructs should always be used - IMO doing other then
this encourages sloppy programming habits. For my own code I always treat a
UE as a programming error on my part. OP can do as they please.