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.
Related
I have a method StartProcess(). I want this method to throw an exception if the same method is called by another thread at the same time or by the same initial thread before EndProcess() is called.
I tried the Monitor class but I wasn't sure how to apply it to the above stated case. What I saw that was close to what I was looking for was:
var obj = new Object();
// Define the critical section.
Monitor.Enter(obj);
try {
// Code to execute one thread at a time.
}
// catch blocks go here.
finally {
Monitor.Exit(obj);
}
I need guidance to handle my exact stated scenario. I've been trying all day but couldn't get it to work.
You need a synchronization mechanism that disallows reentrancy, and the Monitor is not one of them (it is reentrant by design). My suggestion is to use a SemaphoreSlim, which is not reentrant. This mechanism doesn't look to see which thread is calling it. It's just a simple counter. In order to acquire the semaphore if it's available, or return instantly if it's not available, you can invoke the Wait method with a zero millisecondsTimeout, like this:
SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
bool acquired = semaphore.Wait(0);
if (!acquired) throw new InvalidOperationException();
try
{
// Code to execute disallowing concurrency
}
finally
{
semaphore.Release();
}
It seems you are looking for the ManualResetEventSlim:
ManualResetEventSlim resetEvent = new ManualResetEventSlim();
// Block other calls.
resetEvent.Wait();
// Reset state to block next calls.
resetEvent.Reset();
try
{
// Your code
}
finally
{
// Set state to allow next call to proceed.
resetEvent.Set();
}
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've a main thread called t1:
Thread t1 => new Thread(UpdateResults);
that execute a method called UpdateResult this method require internet connection. Now sometimes the connection could be broken.
When the connection is down, the method UpdateResult return an exception and the thread t1 terminate the execution.
I need to execute again the thread t1 so I though to create another thread t2 that check recursively if the thread t1 is running or no.
Both thread are started automatically. This is the code of thread t2 method:
while (true)
{
if (!t1.IsAlive)
{
t1.Start();
}
}
this code unfortuntely slow down the app UI, 'cause is an infinite loop.
What I can do instead for fix this?
Instead of wasting another thread t2 just to watch t1, you may consider to change the method of thread t1:
Thread t1 = new Thread(o =>
{
while (true)
{
try
{
UpdateResult();
}
catch (Exception)
{
// do some error handling
}
Thread.Sleep(100);
}
});
So you catch the exception (without rethrowing it!) and prevent the crash of the whole thread.
This is of course only a simple example. You should try to catch only the specific exception for a broken connection and add proper error handling (e.g. logging etc.).
And adjust the time the thread should sleep according to your needs.
One approach to avoid an infinite polling is to Join the thread, and re-spawn it when it stops:
while (true) {
t1.Join();
t1 = ... // Make a replacement thread
t1.Start();
}
It goes without saying that this should not be done from UI thread, because Join() blocks indefinitely.
If you want to stick with your architecture, something as simple as waiting a second in each loop of Thread t2 would massively improve performance.
while (true)
{
if(!t1.isAlive)
{
t1.Start();
}
Thread.Sleep(1000);
}
(You can adjust the time to anything that makes sense in your context.)
Though instead of this multi-thread solution, i would ask: why does thread t1 terminate because of an Exception? You can catch it with a try-catch block.
Instead of UpdateResults call SafeUpdateResults which just says:
void SafeUpdateResults()
{
while (true)
{
try { UpdateResults(); }
catch (Exception e)
{
//track the Error if you want
Console.WriteLine("t1-Error: " + e.Message);
}
}
}
I would even recommend, going into the function UpdateResults() and catching the Exception right where it happens, and then reacting accordingly (though this here is arguably easier).
I was testing how many threads my computer can handle before something goes wrong, using the following code:
static void Main(string[] args)
{
List<Thread> threads = new List<Thread>();
int count = 0;
try
{
while (true)
{
Console.Write('m'); // make
Thread thread = new Thread(() => { Thread.Sleep(Timeout.Infinite); }, 1024 * 64);
Console.Write('s'); // start
thread.Start();
Console.Write('p'); // suspend
thread.Suspend();
Console.Write('a'); // add
threads.Add(thread);
Console.Write(' ');
Console.WriteLine(count++);
}
}
catch (Exception e)
{
Console.WriteLine("\nGot exception of type " + e.GetType().Name);
}
Console.WriteLine(count);
Console.ReadKey(true);
}
I was expected the new Thread(...) constructor to throw an exception (maybe OutOfMemoryException) when the system could not make any more threads, but instead the constructor hangs and never returns.
Instead of the output from the above being
...
mspa 67
m
Got exception of type OutOfMemoryException
it is rather
...
mspa 67
m <- it hangs while 'm'aking the thread
So, the TLDR: why does new Thread(...) hang instead of throw an exception when there are too many threads?
thread.Suspend();
That's an evil, evil, evil method. Strongly deprecated in .NET version 2.0, it isn't very clear how you got past the [Obsolete] message and not notice this. I'll quote the MSDN note about this method:
Do not use the Suspend and Resume methods to synchronize the activities of threads. You have no way of knowing what code a thread is executing when you suspend it. If you suspend a thread while it holds locks during a security permission evaluation, other threads in the AppDomain might be blocked. If you suspend a thread while it is executing a class constructor, other threads in the AppDomain that attempt to use that class are blocked. Deadlocks can occur very easily.
Yup, that's what a deadlock looks like.
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);
}