Whenever a thread in my ThreadPool throws an exception, my code seems to be stuck at the catch block inside the thread function. How do I get the exception back to the main thread?
The best practice is that your background threads should not throw exceptions. Let them handle their exceptions on their own.
Ideally you should wrap the code in your method that executes on a thread in a try-catch block and handle the exception in the catch block. Do not re-throw it from the catch block.
Read this for more details. http://www.albahari.com/threading/#_Exception_Handling
If you want to update the UI from background thread you can do that by using Control.InvokeRequired property and Control.Invoke method. See the MSDN links for details and examples.
It's not possible to transfer exception from a thread to another one. What can you do is to built some synchronization mechanism to transfer exception information between threads and then throw a new exception from the target thread something like:
class Program
{
Exception _savedException = null;
AutoResetEvent _exceptionEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Program program = new Program();
program.RunMain();
}
void RunMain()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod));
while (true)
{
_exceptionEvent.WaitOne();
if (_savedException != null)
{
throw _savedException;
}
}
}
void ThreadMethod(object contxt)
{
try
{
// do something that can throw an exception
}
catch (Exception ex)
{
_savedException = ex;
_exceptionEvent.Set();
}
}
}
If you have a Win form application things are much simpler. In the catch clause of your thread use Invoke (or BeginInvoke) method of your form, providing it with the exception details. In the method launched with Invoke you can rethrow or treat your exception as you want.
Related
The following code seems as though it should swallow any type of exception in the try block, but the IIS worker process periodically dies and restarts because of an unhandled exception (marked with a comment.)
try
{
while (true)
{
DispatcherTask task = null;
lock (sync)
{
task = this.getTask();
if (task == null)
{
Monitor.Wait(sync);
continue;
}
}
lock (task)
{
task.Result = task.Task.DynamicInvoke(task.Params);
// ^ Delegate.DynamicInvoke(object[]) throws a TargetInvocationException
Monitor.PulseAll(task);
}
}
}
catch (Exception e)
{
}
UPDATE:
Definition of DispatcherTask:
private class DispatcherTask
{
public Delegate Task;
public object[] Params;
public object Result;
}
You cannot catch the exceptions of another thread, at least not in this way. Catch your exception inside the newly opened thread and you will be fine.
In .NET 4 and up, AccessViolationException will bypass catch blocks by default. Catching of such exceptions can be enabled in web.config, but should not be, as they typically result from errors in unmanaged code and signal that the application state is corrupted.
I have an application that are executing 4 different jobs parallel. I use the parallel task library.
The code looks like this:
while (true)
{
var fetch = new FetcherHandler();
var tasks = new Task[4];
tasks[0] = Task.Factory.StartNew(fetch.GetJobs);
tasks[1] = Task.Factory.StartNew(fetch.GetStatusNew);
tasks[2] = Task.Factory.StartNew(fetch.GetJobsForStatus);
tasks[3] = Task.Factory.StartNew(fetch.GetStatusOld);
Task.WaitAll(tasks);
Thread.Sleep(10000);
}
The thread.Sleep above will never be reached since all these 4 tasks is in a never ending loop. Code example for the first task:
public void GetJobs()
{
while (true)
{
try
{
handler.GetNewJob();
}
catch (Exception exception)
{
var mail = new MailService();
mail.SendExeption("Error has accured in GetJobs", exception);
throw;
}
}
}
Thread.Sleep(15000); }}
The above code works great, it does some jobs and then it sleeps for 15 sec, and then it does it again. The problem occurres when I get an exception.
The exception is caught alright, and sends me an mail, but the thred doesn't continue in the loop after the exception, so the GetNewJob() method will never get executed again.
Any ideas what happens to the thread when exception hits, and how I can "save" the thread so it can continue?
Becasue you throw an exception, so the exception propagates on top of the stack and break execution of the source thread.
catch (Exception exception)
{
var mail = new MailService();
mail.SendExeption("Error has accured in GetJobs", exception);
throw; //THIS LINE !
}
You can use an event to raise it, say, ExceptionCaught(..) and listen for that event inside your program.
Just remove the throw; at the end of your catch clause.
From MSDN:
A throw statement can be used in a catch block to re-throw the
exception that is caught by the catch statement.
So you're rethrowing the caught exception which causes the thread to interrupt, never executing again...
More information: What happens when a .NET thread throws an exception?
I currently have a small console application that runs a number of Tasks (using Parallel.ForEach) and each one of these tasks creates sub-threads using ThreadPool.QueueUserWorkItem.
I would like the application to handle any exception thrown by these tasks/threads.
Will surrounding the Parallel.ForEach statement with try..catch work if the threads throw any errors or will they just die out?
EDIT: These sub-threads simulate users of the system. Refer to this question.
Surrounding the statement will not do the job. You can do something like this:
public static void Main(string[] args)
{
string[] files = System.IO.Directory.GetFiles(#".", "*.*");
Parallel.ForEach(files, x =>
{
try
{
MyAction(x);
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
});
}
static void MyAction(string x)
{
throw new ApplicationException("Testing: " + x);
}
Don't use QUWI. I have a brief comparison of background task types on my blog (Task, BackgroundWorker, Delegate.BeginInvoke, ThreadPool.QueueUserWorkItem, and Thread).
For background tasks, Task is the clear winner. QueueUserWorkItem is very low-level by comparison.
In particular, your problem is error propogation, and Task has built-in support for this that is entirely lacking in QueueUserWorkItem. You could build it in yourself by wrapping your delegate in a try/catch, storing the exception as part of the delegate argument (or as a bound variable of a lambda expression), explicitly checking it later, and doing some technically unsupported reflection to preserve the stack trace.
But why bother? Task supports error propogation out of the box.
you can handle all exceptions with try/catch, for example:
try
{
MyParallelMethod();
}
catch(Exception e)
{
//...
}
and in your method, do something like that:
public void MyParallelMethod()
{
var data = new List<String>();
//...
Parallel.ForEach(data, d =>
{
try
{
//...
}
catch (Exception e)
{
//...
}
});
}
Will surrounding the Parallel.ForEach statement with try..catch work if the threads throw any errors or will they just die out?
No, you need to put try/catch inside the sub threads.
Error handling must be implemented in the task itself (the job each ). You need to make sure the task you are creating handles the exception.
Parallel.ForEach will not handle it for you since the exception will be raised not in the thread which is calling the Parallel.ForEach.
Alternative is to use Task<T>.
I am trying to prevent a task from continuing if the first part fails.
My code looks like that:
Task listener = Task.Factory.StartNew(openConnection).ContinueWith((t) => listenForNumber());
void openConnection()
{
try
{
//stuff
}
catch
{
//morestuff
}
}
void listenForNumber()
{
//even more stuff
}
Now listenForNuber() should not be executed if openConnection() enters the catch block
I tried ContinueWith((t) => listenForNumber(),TaskContinuationOptions.NotOnFaulted);
But no success, any help? :(
Thanks
TaskContiuationOptions.NotOnFaulted will obviously have no effect unless your method has faulted, i.e. an exception thrown during its execution was unhandled.
In your catch block, you should re-throw the exception (and preserve the stack trace) using the throw; statement after you've performed your work (some clean-up maybe) - otherwise the exception won't be thrown again, so your method will not be considered as 'faulted'.
Create an extension method helper.
public static void PropagateExceptions(this Task task)
{
if (task == null)
throw new ArgumentNullException("task");
if (!task.IsCompleted)
throw new InvalidOperationException("The task has not completed yet.");
if (task.IsFaulted)
task.Wait();
}
then call PropagateExceptions() extension method before executing any codes. PropagateExceptions() method will also rethrow if the task was cancelled.
t1.ContinueWith(t => {
t.PropagateExceptions();
listenForNumber();
});
You need to throw the exception in your task method. The TPL does not know the method has failed, unless it catches an exception.
You will still need to have a continuation method for the faulted case. This could be a simple method that logs the exception.
If you don't have a continuation method for the exception, you will get unhandled exceptions in your application when your task method throws an exception.
In ASP.NET web application a worker thread creates a non-threadpool thread like the below:
private static bool _refreshInProcess = false;
public delegate void Refresher();
private static Thread _refresher;
private static void CreateAndStartRefreshThread(Refresher refresh)
{
_refresher = new Thread(new ThreadStart(refresh));
_refresher.Start();
}
private static void Refresh()
{
LoadAllSystemData();
}
static public void CheckStatus()
{
DateTime timeStamp = DateTime.Now;
TimeSpan span = timeStamp.Subtract(_cacheTimeStamp);
if (span.Hours >= 24)
{
if (Monitor.TryEnter(_cacheLock))
{
try
{
if (!_refreshInProcess)
{
_refreshInProcess = true;
CreateAndStartRefreshThread(Refresh);
}
}
finally
{
Monitor.Exit(_cacheLock);
}
}
}
}
static public void LoadAllSystemData()
{
try
{
if (!Database.Connected)
{
if (!OpenDatabase())
throw new Exception("Unable to (re)connect to database");
}
SystemData newData = new SystemData();
LoadTables(ref newData);
LoadClasses(ref newData);
LoadAllSysDescrs(ref newData);
_allData = newData;
_cacheTimeStamp = DateTime.Now; // only place where timestamp is updtd
}
finally
{
_refreshInProcess = false;
}
}
and LoadAllSystemData() is also called elsewhere from the same lock-guarded section as CheckStatus(). Both calls are in their try-blocks that also have catch-block.
Now my questions are
If LoadAllSystemData throws an exception when it's called from a non-threadpool thread in method Refresh, what will happen? Nobody can catch it.
What happens when it's done 1000 times? Are these exceptions stored somewhere and thus stress the system and ultimately crash it due to memory exhaustion or something?
Is there a good solution to catch them without waiting in the creating thread pool thread for the created thread to finish?
Thanks a lot!
If exception is raised in the background non-threadpool thread and eventually it is not handled by any catch block, it is propagated up until it reaches beginning of the stack. Then thread finishes its execution - exception is not stored anywhere. Then the thread is dropped as well as its stack containing reference to the exception.
Exception throwing is expensive in .NET so if you anticipate 1000 times it to occur, probably it is not an exception but just a part of your application flow and you should not raise an exception here.
If you want to catch the exceptions from background activity, as an option you can use delegate's BeginInvoke / EndInvoke methods. If there is any exception in the background operation, it will be delivered in the EndInvoke call.