views:

171

answers:

6

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.

+1  A: 

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.

Dani
Agree. I don tsee that as an issue - you start a thread, it goes into a method of yours.... so what stops you from handling exceptions there?
TomTom
+2  A: 

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.

Sean
You can't catch ThreadAbortException in .Net 3.5 or below with default settings and you can't catch exceptions that might represent corrupted state in .Net 4.0, also with default settings.So you can't catch all exceptions with a try catch block using default settings (it's not recommended that you do either)
Pop Catalin
It doesn't throw a ThreadAbortException unless you abort the thread - also you can catch them, but not swallow them as they're re-raised automatically
Chris S
@Chris S, you're right +1, I've used catching with the meaning of swallowing, which is not politically correct.
Pop Catalin
+1  A: 

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)
{
}
}
Chris
A: 

You can use ManualResetEvent-MSDN

Notifies one or more waiting threads that an event has occurred.

class Test
{
    static void Main()
    {
        ManualResetEvent[] events = new ManualResetEvent[20];
        var runners = new List<Thread>();

        for (int i = 0; i < events.Length; i++)
        {
            events[i] = new ManualResetEvent(false);

            Runner r = new Runner(events[i], i);
            var t = new Thread(new ThreadStart(r.Run));
            runners.Add(t);
            t.Start();
        }

        while (true)
        {
            int index = WaitHandle.WaitAny(events);
            events[index].Reset();
            runners[index].Join();
            Console.WriteLine("Exception in {0}", index);
        }

    }
}

class Runner
{
    static readonly object rngLock = new object();
    static Random rng = new Random();

    ManualResetEvent ev;
    int id;

    internal Runner(ManualResetEvent ev, int id)
    {
        this.ev = ev;
        this.id = id;
    }

    internal void Run()
    {
        Console.WriteLine("Running {0}", this.id);
        try
        {
            if (rng.Next(10) == 5 || rng.Next(10) == 3) 
                throw new Exception(string.Format("Very Dangerous Exception in {0}",this.id));

            Thread.Sleep(1000);

            Console.WriteLine("{0} done",this.id);

        }
        catch (Exception ee)
        {
            //Console.WriteLine(ee.Message);
            ev.Set();

        }
    }
}

from> http://www.yoda.arachsys.com/csharp/threads/waithandles.shtml

TheMachineCharmer
+5  A: 

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);
Chris S
+1  A: 

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.

Enigmativity