I want to know if
try/catch can catch the exceptions thrown by the children threads.
if not, what's the best practice to handling exceptions thrown in the child thread.
You can listen to the Application.ThreadException and AppDomain.UnhandledException events to catch uncaught exceptions from thread. But the best is to catch and handle exceptions in the threads themselves. This should be a last resort for graceful shutdown / logging.
It depends on the .NET framework you're targeting.
In 1.1 and lesser, exceptions thrown by children threads will be forwarded to the main thread only if they run outside a try/catch block.
In 2.0 and later, this behaviour is changed: thread will be terminated and exceptions won't be allowed to proceed any further.
Anyway, you can handle exceptions inside a thread as you would do in a single-threaded application.
See http://msdn.microsoft.com/en-us/library/ms228965(v=VS.90).aspx for reference.
No, consider the following code:
try
{
var t = new Thread(()=>
{
Thread.Sleep(5000);
throw new Exception();
});
t.Start();
//t.Join();
}
catch
{
//you can't deal with exception here
//even though you uncomment `t.Join`
}
Deal with exceptions in the child thread which the exceptions "belongs" to.
Related
method A()
{
try
{
Thread t = new Thread(new ThreadStart(B));
t.Start();
}
catch(exception e)
{
//show message of exception
}
}
method B()
{
// getDBQuery
}
a exception in B but not catched.
does it legal in .net?
Correct, exceptions from a Thread are not forwarded to the caller, the Thread should handle this by itself.
The most general answer is that you should not be using a (bare) Thread here. It's not efficient and not convenient.
When you use a Task, the exception is stored and raised when you cal Wait() or Result.
When A is finished executing B might still be running as it is on an independent thread. For that reason it is impossible by principle for A to catch all exceptions that B produces.
Move the try-catch to inside of B. The Thread class does not forward exceptions.
Better yet, use Task which allows you to propagate and inspect exceptions.
I am using the following event to catch unhandled exceptions in the main UI thread.
Application.ThreadException
Unfortunately, it does not catch those unhandled errors in seperate threads. I am aware of
AppDomain.CurrentDomain.UnhandledException
However, this seems to shut down the application upon triggering, where as the former does not.
Is there a way to deal with unhandled exceptions on separate threads, without the application closing?
#Ani have already answered your question. Although I don't agree that unhandled exceptions in threads should terminate applications. Using threads usually means that you have some kind of server application. Bringing it down could result in a lot of angry users.
I've written a small piece about proper exception handling: https://coderr.io/exception-handling
You should always catch exceptions for threads. I usually use the following pattern:
void ThreadMethod(object state)
{
try
{
ActualWorkerMethod();
}
catch (Exception err)
{
_logger.Error("Unhandled exception in thread.", err);
}
}
void ActualWorkerMethod()
{
// do something clever
}
It's a whole lot easier to find thread methods that doesn't handle exceptions properly by moving the logic into a seperate method and just keep the try/catch block in the thread method.
Of course you should always handle all exceptions. But if you are currently incapable of doing so, you can try the following:
The application will crash/close after the UnhandledException event handler.
You can just add a delay in the event handler to prevents this. Other threads with no exception (e.g. the main thread) can continue. So the application will not close and can continue. However, the thread with the exception will remain in sleep. And therefor you may get a "memory/thread leak".
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// Log the exception, display it, etc
Debug.WriteLine((e.ExceptionObject as Exception).Message);
Thread.Sleep(100000000);
}
At this moment there is not a better solution.
You may find to change the config file, but i think that is just as dirty: https://stackoverflow.com/a/15348736
Yes, you have to manually catch exceptions on threads.
However, this code:
void ThreadMethod(object state)
{
try
{
ActualWorkerMethod();
}
catch (Exception err)
{
_logger.Error("Unhandled exception in thread.", err);
}
}
void ActualWorkerMethod()
{
// do something clever
}
can be simplified to this using PostSharp:
[LogExceptions]
void ActualWorkerMethod()
{
// do something clever
}
I have an application that is mixed Winforms and WPF. In Winforms, I have a global exception handler that is defined as follows:
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.ThreadException += Application_ThreadException;
This ALWAYS catches exceptions anywhere in my application that occur that are not expected and handled gracefully.
For WPF, all I seem to be able to capture is:
wpfAppDomain = new System.Windows.Application();
wpfAppDomain.DispatcherUnhandledException +=
wpfAppDomain_DispatcherUnhandledException;
This does NOT always catch global exceptions, and I often find that exceptions are swallowed somewhere and I'm not sure why.
How can I make a global exception handler for WPF that can catch any exception that occurs that is unhandled?
There are several cases where this code will not catch an exception and do so by design
The exception is simply uncatchable. For example a runtime thrown StackOverflowException
The exception is unhandled in your code, but caught in the core WPF framework.
There is no way to catch all thrown exceptions. To do so would allow you to violate semantics of code that should always work.
Have you tried this after calling SetUnhandledExceptionMode? Like this:
// Force all exceptions through our handler.
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
DispatcherUnhandledException only catches exception from code called by a dispatcher (like the name suggests), it is supposed to catch exceptions thrown when called from WPF code.
It does not cover exceptions thrown from: WinForms, BackgroundWorker, the thread pool or threads you started yourself.
you can still use AppDomain.CurrentDomain.UnhandledException to catch those.
I have a dialog that has to process large quantaties of data (the procedure is quite time consuming - first the ODBC fill takes its time, then the data processing kicks in) and the result is that the Form becomes unresponsive. This is not a problem really, it is enough to just open a "loading screen" in a new thread to notify the user of the process.
Recently I have discovered, that sometimes (it appears to be random) the new thread will throw an unhandled ThreadAbortException causing a crash report dialog box to show up (or JIT).
I do not understand why this exception would be thrown, or why it would be unhandled. Has anyone dealt with this before, or can anyone point me towards the probable cause of this behaviour?
Thank you!
EDIT: In case it matters, I open the loading screen like this:
//start of work load
Thread th = new Thread(new ThreadStart(MakeStep));
th.Start();
...
//end of work or error occurance:
th.Abort();
//
You're calling th.Abort() which injects a ThreadAbortException on the thread th. If that thread doesn't handle the exception it will be reported as an unhandled exception.
It is generally not recommended to abort other threads in this way, as you have no idea if the thread will handle an abort gracefully. A better solution is to use signaling between your threads.
ThreadAbortExceptions are raised when you call Thread.Abort(). Looks like you or a lib you are using is trying to kill your Thread.
If you don't know why it's aborting, better to let it go than to swallow the exception.
That being said, you need to wrap your MakeStep method in a try/catch and log the exception (and, of course, any innter exceptions). Something like this...
public void MakeStep()
{
try
{
InnerMakeStep(); // may throw TAE or some other exception
}catch(Exception e)
{
// log here k
throw; // in case it isn't a TAE
}
}
With the exception logged, the issue can be debugged. Right now, it could be a thousand things.
The code that I want to write is like this:
void MethodOnThreadA()
{
for (;;)
{
// Do stuff
if (ErrorConditionMet)
ThrowOnThread(threadB, new MyException(...));
}
}
void MethodOnThreadB()
{
try
{
for (;;)
{
// Do stuff
}
}
catch (MyException ex)
{
// Do the right thing for this exception.
}
}
I know I can have thread B periodically check, in thread safe way, to see if a flag has been set by thread A, but that makes the code more complicated. Is there a better mechanism that I can use?
Here is a more fleshed out example of periodically checking:
Dictionary<Thread, Exception> exceptionDictionary = new Dictionary<Thread, Exception>();
void ThrowOnThread(Thread thread, Exception ex)
{
// the exception passed in is going to be handed off to another thread,
// so it needs to be thread safe.
lock (exceptionDictionary)
{
exceptionDictionary[thread] = ex;
}
}
void ExceptionCheck()
{
lock (exceptionDictionary)
{
Exception ex;
if (exceptionDictionary.TryGetValue(Thread.CurrentThread, out ex))
throw ex;
}
}
void MethodOnThreadA()
{
for (;;)
{
// Do stuff
if (ErrorConditionMet)
ThrowOnThread(threadB, new MyException(...));
}
}
void MethodOnThreadB()
{
try
{
for (;;)
{
// Do stuff
ExceptionCheck();
}
}
catch (MyException ex)
{
// Do the right thing for this exception.
}
}
This is NOT a good idea
This article talks about ruby's timeout library. which throws exceptions across threads.
It explains how doing such a thing is fundamentally broken. It's not just broken in ruby, it's broken anywhere that throws exceptions across threads.
In a nutshell, what can (and does) happen is this:
ThreadA:
At some random time, throw an exception on thread B:
ThreadB:
try {
//do stuff
} finally {
CloseResourceOne();
// ThreadA's exception gets thrown NOW, in the middle
// of our finally block and resource two NEVER gets closed.
// Obviously this is BAD, and the only way to stop is to NOT throw
// exceptions across threads
CloseResourceTwo();
}
Your 'periodic checking' example is fine, as you're not actually throwing exceptions across threads.
You're just setting a flag which says "throw an exception the next time you look at this flag", which is fine as it doesn't suffer from the "can be thrown in the middle of your catch or finally block" problem.
However, if you're going to do that, you may as well just be setting an "exitnow" flag, and using that and save yourself the hassle of creating the exception object. A volatile bool will work just fine for that.
There are enough problems with exceptions that can be thrown on threads by other mechanisms, like aborting threads and the likes, that you should find another way of doing it.
An exception is a mechanism used to signal that a process has experienced something exceptional that it cannot deal with. You should try to avoid writing the code so that an exception is used to signal that something else has experienced something exceptional.
That other thread will most likely not know how to handle the exception in all cases where it could be thrown by your code.
In short, you should find some other mechanism for aborting your threads than using exceptions.
Use event objects or similar to tell a thread to abort its processing, that's the best way.
What Orion Edwards is saying is not entirely true: is not the "only" way.
// Obviously this is BAD, and the only way to stop is to NOT throw
// exceptions across threads
Using CER (Constrained Execution Regions) in C# allows you to release your resources as an atomic operation, protecting your code from inter-thread exceptions. This technique is used by several classes of the .NET Framework which work with Windows' native API, where an unreleased handle may cause a memory leak.
See http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions.aspx
The following example shows how to reliably set handles by using the PrepareConstrainedRegions method. To reliably set a handle to a specified pre-existing handle, you must ensure that the allocation of the native handle and the subsequent recording of that handle within a SafeHandle object is atomic. Any failure between these operations (such as a thread abort or out-of-memory exception) will result in the native handle being leaked. You can use the PrepareConstrainedRegions method to make sure that the handle is not leaked.
As simple as:
public MySafeHandle AllocateHandle()
{
// Allocate SafeHandle first to avoid failure later.
MySafeHandle sh = new MySafeHandle();
RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally // this finally block is atomic an uninterruptible by inter-thread exceptions
{
MyStruct myStruct = new MyStruct();
NativeAllocateHandle(ref myStruct);
sh.SetHandle(myStruct.m_outputHandle);
}
return sh;
}
While researching another issue, I came across this article which reminded me of your question:
Plumbing the Depths of the ThreadAbortException using Rotor
It shows the gyrations that .NET goes through to implement Thread.Abort() -- presumably any other cross-thread exception would have to be similar. (Yeech!)
I'm interested to know why you would want to do this. There's not an easy way to do it, because it's not a good practice. You should probably go back to your design and figure out a cleaner way to accomplish the end goal.
I don't think that's a good idea..
Take another crack at this problem - Try using some other mechanism like shared data to signal between threads.
Like the others, I'm not sure that's such a good idea, but if you really want to do it, then you can create a subclass of SynchronizationContext that allows posting and sending delegates to the target thread (if it's a WinForms thread the work is done for you as such a subclass already exists). The target thread will have to implement some sort of a message pump equivalent though, to receive the delegates.
#Orion Edwards
I take your point about an exception being thrown in the finally block.
However, I think there is a way - using yet another thread - of using this exception-as-interrupt idea.
Thread A:
At some random time, throw an exception on thread C:
Thread B:
try {
Signal thread C that exceptions may be thrown
//do stuff, without needing to check exit conditions
Signal thread C that exceptions may no longer be thrown
}
catch {
// exception/interrupt occurred handle...
}
finally {
// ...and clean up
CloseResourceOne();
CloseResourceTwo();
}
Thread C:
while(thread-B-wants-exceptions) {
try {
Thread.Sleep(1)
}
catch {
// exception was thrown...
if Thread B still wants to handle exceptions
throw-in-B
}
}
Or is that just silly?