zzfima
zzfima

Reputation: 1565

Catch exception in current thread when it's thrown in different thread

My situation is:

from main thread i start thread A. In main thread there some while(true) which run a lot of time. Inside of while is time consumption operations:

    static void Main(string[] args)
    {
        new Thread(Go).Start();

        while (true)
        {
            Thread.Sleep(1000);
        }
    }

    private static void Go()
    {
    }

I wish generate exception in main thread if something go wrong in thread A

I read some articles, for example this one: catch exception that is thrown in different thread

and the only answer is: using shared variable (one of answers)

So, solution:

    static void Main(string[] args)
    {
        new Thread(Go).Start();

        while (true)
        {
            Thread.Sleep(1000);

            if (_bad)
            {
                throw new Exception();
            }
        }
    }

    private static void Go()
    {
        Thread.Sleep(4000);
        _bad = true;
    }

is unacceptable, because i wish get exception ASAP. Not wait for loop cycling. For example, if i do cook cookies in while loop, i do not want wait for next cycle when i heat out: when heater is broken i wish in same moment generate exception in main thread.

Now, i can not pass delegates to thread: if i call delegate from thread A, is can not cut while loop, because it other thread. Same thing about events.

How can i handle this problem?

Thanks

Upvotes: 2

Views: 850

Answers (2)

Sam Harwell
Sam Harwell

Reputation: 99859

The best way to achieve this is using the Task Parallel Library. If you start your task with TaskCreationOptions.LongRunning, a new thread will be created for the execution of the body of the task. You can then either access Task<T>.Result or call Wait from the main thread, and the exception (if any) will be propagated back to the thread. Use a CancellationTokenSource to support cancellation of other operations that are executing concurrently with the Go operation.

In the following example, calls to Thread.Sleep are placeholders for application-specific time consuming operations.

private static CancellationTokenSource _cancellationTokenSource =
    new CancellationTokenSource();

static void Main(string[] args)
{
    Task longRunning = Task.Factory.StartNew(Go, TaskCreationOptions.LongRunning);
    while (true)
    {
        // Pass _cancellationTokenSource.Token to worker items to support
        // cancelling the operation(s) immediately if the long running
        // operation throws an exception
        Thread.Sleep(1000);

        // this will throw an exception if the task faulted, or simply continue
        // if the task is still running
        longRunning.Wait(0);
    }
}

private static void Go()
{
    try
    {
        Thread.Sleep(4000);
        throw new Exception("Oh noes!!");
    }
    catch
    {
        _cancellationTokenSource.Cancel();
        throw;
    }
}

Upvotes: 1

Darryl
Darryl

Reputation: 6217

As some of the related questions suggest, use a BackgroundWorker. If the worker thread raises an exception, it gets passed to the main thread via the RunWorkerCompleted event. See http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.runworkercompleted(v=vs.110).aspx.

Upvotes: 0

Related Questions