in VS2008 I have a program and it occasionally has an issue where a consumer thread stops processing work. When I looked the ThreadState says Stopped. What caused the thread to stop? I didn't stop it. There were no exceptions. Seems really strange.
thanks
Maybe the thread is terminated?
According to this: http://msdn.microsoft.com/en-us/library/system.threading.threadstate.aspx
a thread is in Stopped state only if it's terminated or if it responds to an abort request.
Are you sure there's no exception?
A try catch on your main thread will not catch exceptions on a worker thread.
In the starting method on the other thread, have a try catch block, then there either raise an event back on the main thread, or cache the exception on a property on the object that has the starting method, then check that property in the main thread.
Hope this helps.
e.g.
class Worker
{
public Exception TheadException { get; private set; }
public void Start()
{
try
{
// Do your thing
}
catch (Exception ex)
{
TheadException = ex;
}
}
}
....
static void Main(string[] args)
{
Worker workerObject = new Worker();
var workerThread = new System.Threading.Thread(workerObject.Start);
workerThread.Start();
workerThread.Join();
if (workerObject.TheadException != null)
Console.WriteLine("Thread failed with exception {0}", workerObject.TheadException);
}
Related
Thread version results in unhandled exception, which crashes the app but the task version doesn't. Both are running exactly the same method Can someone explain the reason for this difference in exception behavior ?
Thread version:
try
{
new Thread(new ThreadStart(DoWork)).Start(); // do work throws exception
}
catch (Exception e)
{
Console.WriteLine(e);
}
static void DoWork()
{
Console.WriteLine("in thread");
throw new Exception();
}
Task version:
var errorTask = Task.Factory.StartNew<Func<string>>(() =>
{
Console.WriteLine("in task");
throw new Exception();
});
try
{
string result = errorTask.Result();
}
catch (Exception e)
{
Console.WriteLine(e);
}
Thread.Start starts new thread, but you're handling exception in another thread:
try
{
// DoWork throws exception in new thread;
// threads don't catch exceptions out-of-the-box
new Thread(new ThreadStart(DoWork)).Start();
}
catch (Exception e)
{
// you're handling exception in "old" thread
Console.WriteLine(e);
}
Task.Factory.StartNew starts new task. Task catches exception inside it to set its Status property:
var errorTask = Task.Factory.StartNew<Func<string>>(() =>
{
Console.WriteLine("in task");
// this exception will be caught in Task's base code,
// since tasks catch exceptions thrown by task methods;
// note, that this will be wrapped into AggregateException
throw new Exception();
});
when you're trying to get Task.Result, and task is in faulted state, it just re-throws exception:
// this will re-throw exception in calling thread
string result = errorTask.Result;
That's why your second catch catches it.
To shed some light on the topic one could consult the documentation for Task.Result<TResult>() (or the one for Task.Wait() for what it's worth).
Under thrown exceptions (particularly AggregateException) is says
An exception was thrown during the execution of the task. The AggregateException.InnerExceptions collection contains information about the exception or exceptions.
A Task is kind of a managed thread (in very simple terms) which gives us some merits, e.g. this exception handling when accessing Result or Wait (or using await). On the other hand a Thread will execute separately from the method you are calling it from. You start the thread an (virtually) immediately leave the try / catch block. There is no way to know for the thread that there is an associated try / catch. Basically the thread does not know anything about the calling function. The other way round, if the calling function blocked its own thread to wait for the thread it created, just to make use of the try / catch this would basically render creating new threads useless.
I try to catch exceptions from another thread, but can't.
static void Main(string[] args)
{
try
{
Task task = new Task(Work);
task.Start();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine();
}
public static void Work()
{
throw new NotImplementedException();
}
I write try-catch and at method too, but nothing happens.
Please,tell me how to know that exception throw?
Maybe you could show me some example code.
Your code may not raise the exception as the main method will executes too fast and the process will terminate before you got the exception
Here how it would look your code
static void Main(string[] args)
{
Task task = new Task(Work);
task.Start();
var taskErrorHandler = task.ContinueWith(task1 =>
{
var ex = task1.Exception;
Console.WriteLine(ex.InnerException.Message);
}, TaskContinuationOptions.OnlyOnFaulted);
//here you should put the readline in order to avoid the fast execution of your main thread
Console.ReadLine();
}
public static void Work()
{
throw new NotImplementedException();
}
Try to take a look at ContinueWith
The OnlyOnFaulted member of the TaskContinuationOptions enumeration
indicates that the continuation should only be executed if the
antecedent task threw an exception.
task.ContinueWith((Sender) =>
{
////This will be called when error occures
Sender.Result
}, TaskContinuationOptions.OnlyOnFaulted);
Your try/catch wouldn't work. For one reason : because you could very well have gone out of the try block before the exception is thrown, as the Task is done on another thread.
With a Task, there are two ways to get the exceptions.
The first one is to use task.Wait(); in your try block. This method will rethrow any exception thrown by the task.
Then, any exception will be handled on the calling thread in the catch block.
The second one is to use the ContinueWith method. This won't block your calling thread.
task.ContinueWith(t =>
{
// Here is your exception :
DoSomethingWithYour(t.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
Note the following will block the main thread since Wait is employed.
try
{
Task task = Task.Factory.StartNew(Work);
task.Wait();
}
catch (AggregateException ex)
{
Console.WriteLine(ex.ToString());
}
If I have the following situation:
Execute() creates a new thread and executes function GetSession() in it.
Execute() executes GetSession() again in it's own thread.
Execute() joins the thread from (1).
My question is:
What happens if GetSession() throws an exception from the thread spawned in (1) while the thread Execute() is running in is currently running GetSession() itself?
Does the exception re-thrown from the extra thread propagate up to Execute() and cause it to go to its handler even though it's from a different thread?
Here's some sample code to demonstrate the issue:
I just made this up in the window here (it's a mock-up), so appologies for syntax errors.
public void Execute()
{
//Some logon data for two servers.
string server1 = "x", server2 = "y", logon = "logon", password = "password";
//Varialbes to store sessions in.
MySession session1, session2;
try
{
//Start first session request in new thread.
Thread thread = new Thread(() =>
session1 = GetSession(server1, logon, password));
thread.Start();
//Start second request in current thread, wait for first to complete.
session2 = GetSession(server2, logon, password));
thread.Join();
}
catch(Exception ex)
{
//Will this get hit if thread1 throws an exception?
MessageBox.Show(ex.ToString());
return;
}
}
private MySession GetSession(string server, string logon, string password)
{
try
{
return new MySession(server, logon, password);
}
catch(Exception Ex)
{
throw(Ex);
}
}
What happens if GetSession() throws an exception from the thread spawned in (1) while the thread Execute() is running in is currently running GetSession() itself?
The threaded version will raise an unhandled exception, which will trigger AppDomain.UnhandledException. Unless this is explicitly handled there, it will tear down the application.
Does the exception re-thrown from the extra thread propagate up to Execute() and cause it to go to its handler even though it's from a different thread?
No. It will be unhandled.
Note that this is one of the advantages of the TPL. If you use Task instead of a Thread, you can make this propogate the exception back to the main thread:
try
{
//Start first session request in new thread.
Task<Session> task = Task.Factory.StartNew(() => GetSession(server1, logon, password));
//Start second request in current thread, wait for first to complete.
session2 = GetSession(server2, logon, password));
session1 = task.Result; // This blocks, and will raise an exception here, on this thread
}
catch(Exception ex)
{
// Now this will get hit
MessageBox.Show(ex.ToString());
return;
}
Note, however, that this will be an AggregateException, and requires special handling.
RulyCanceler canceler = new RulyCanceler();
Thread workerThread = new Thread(() =>
{
try { Work(canceler, crawler, propertyBag); }
catch (OperationCanceledException e)
{
LogError.WriteError("Working thread canceled!" + Environment.NewLine);
LogError.WriteError(e);
}
catch (Exception e)
{
LogError.WriteError(e);
}
});
workerThread.Start();
bool finished = workerThread.Join(120000);
if (!finished)
{
LogError.WriteError("Aborting thread");
workerThread.Abort();
}
I can not figure out if my program stop all threads when Abort is calling or just current thread and program still executing. Sometime program stop unexepected but i do not know if abort is guilty. Can someone tell me?
EDIT:
I modify class like John suggest
class RulyCanceler
{
readonly object _cancelLocker = new object();
bool _cancelRequest;
private bool IsCancellationRequested
{
get { lock (_cancelLocker) return _cancelRequest; }
}
public void Cancel() { lock (_cancelLocker) _cancelRequest = true; }
public void ThrowIfCancellationRequested()
{
if (IsCancellationRequested) throw new OperationCanceledException();
}
}
class Test
{
static void Main()
{
var canceler = new RulyCanceler();
new Thread (() => {
try { Work (canceler); }
catch (OperationCanceledException)
{
Console. WriteLine ("Canceled! ");
}
}). Start();
Thread. Sleep (1000);
canceler. Cancel(); // Safely cancel worker.
}
static void Work (RulyCanceler c)
{
while (true)
{
c. ThrowIfCancellationRequested();
// . . .
try { OtherMethod (c); }
finally { /* any required cleanup */ }
}
}
Thread.Abort will only abort the thread which you call it on. However, it's a really bad way of terminating a thread - you should do it in a more controlled and cooperative way. Thread.Abort is a safe way of aborting the currently executing thread, but otherwise you don't know that the thread is at a suitable place to abort without leaving the application in an inconsistent state. You should usually reserve it for times when your whole application is going down anyway.
If you want to know what's taking your application down then attach an event handler to the AppDomain.UnhandledException event and log the stacktrace (or set a debug break point).
How could you find out that an Exception occurred in a Thread in a MultiThreaded Application ? and consecutively clean the resources ?
Because otherwise the Thread can be still remaining in memory and running.
As Sean has said, you have to do all exception handling and cleanup inside the thread method, you can't do it in the Thread initialization. For example:
public void Run()
{
try
{
Thread thread1 = new Thread(ThreadEntry1);
thread1.Start();
Thread thread2 = new Thread(ThreadEntry2);
thread2.Start();
}
catch (NotImplementedException)
{
// Neither are caught here
Console.WriteLine("Caught you");
}
}
private void ThreadEntry1()
{
throw new NotImplementedException("Oops");
}
private void ThreadEntry2()
{
throw new NotImplementedException("Oops2");
}
Instead, this approach is more self-contained and obviously also works:
public void Run()
{
Thread thread1 = new Thread(ThreadEntry1);
thread1.Start();
}
private void ThreadEntry1()
{
try
{
throw new NotImplementedException("Oops");
}
catch (NotImplementedException)
{
Console.WriteLine("Ha! Caught you");
}
}
If you want to know if the Thread has failed, then you should consider an array of WaitHandles, and signal back to your calling method. An alternative and simpler approach is to simply increment a counter each time a thread's operation finishes:
Interlocked.Increment(ref _mycounter);
If you're worried about this sort of thing then you should wrap your threads entry point in a try/catch block and do the cleanup explicitly. Any exception passing out of the thread entry point will cause your app to shut down.
A. You have a call stack, and you can catch it inside the thread and add the thread id to the log I guess...
If you wrap your thread in a good manner, you can add cleaing code to the catch section, terminating the thread if needed.
You can catch exceptions within threads like you would any normal function.
If your "work" function for a thread is called DoWork then do something like this:
private void DoWork(...args...)
{
try
{
// Do my thread work here
}
catch (Exception ex)
{
}
}
Eric Lippert has a recent post on the badness of exceptions occurring in worker threads. It's worth reading and understanding that an exception is "exceptional" and the only thing that you can be sure of after an exception in a worker thread is that you can no longer be sure of the state of your application.