2

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

Community
  • 1
  • 1
zzfima
  • 1,528
  • 1
  • 14
  • 21
  • 2
    There's no point in creating a new thread if the thread that creates it is going to do nothing but wait for it to finish. – Servy Apr 07 '14 at 19:37
  • If you want a *really* hacky solution (that I don't recommend), you can pass a reference to the main thread (`Thread.CurrentThread`) to the second thread (that runs `Go`), and abort the main thread from the second thread when an exception occurs. You can then catch the `ThreadAbortException` on the main thread and cancel it. Beware that there's lots of gotchas with this approach! – Cameron Apr 07 '14 at 19:40
  • that's why Join'ing is simpler.. lol – T McKeown Apr 07 '14 at 19:47
  • Servy - i wish start thread of some time consumption operation (for example go to the store and buy sugar) while in main thread in while i bake cookie. How did You decided it do nothing? – zzfima Apr 07 '14 at 19:49
  • Guys, i can not use Join or some WaitOne because i need continue do things. – zzfima Apr 07 '14 at 19:51
  • then use an event and be done with it... – T McKeown Apr 07 '14 at 19:52
  • @TMcKeown: But who's listening for the event? The event handler will be run on the thread that raises it, unless it's marshalled somehow, which basically gives the same result as polling a variable (just with a message pump instead). – Cameron Apr 07 '14 at 19:55
  • in that event implementation abort the main thread.... all that is needed is a way to reference the main thread. – T McKeown Apr 07 '14 at 19:55
  • 1
    @zzfima *You* said you were doing nothing when you provided code in which you do nothing but call `Sleep`. – Servy Apr 07 '14 at 19:59
  • @TMcKeown That's a *really* bad idea. The vast majority of code written simply isn't design to work properly when an exception can be thrown at any arbitrary point in time. It's likely to cause all sorts of subtle bugs, unusual race conditions, and general mayhem. – Servy Apr 07 '14 at 20:00
  • i loathe these horribly written questions... we should get points for the time it takes off our lives. – T McKeown Apr 07 '14 at 20:01
  • @Servy, i'm not the one who wants to abort/stop the main thread upon an exception in another thread. In reality the main thread should have launched all the workers and be doing as little as possible. The poster apparently has his main thread in some sort of state that it can't do it's job. – T McKeown Apr 07 '14 at 20:03

2 Answers2

1

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;
    }
}
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • The exception is only propagated when the task is poked, though. How is this different from polling a variable? – Cameron Apr 07 '14 at 20:02
  • @Cameron Then call `Wait()` to block the main thread waiting for the result of the other thread. The exception will be thrown immediately. – Sam Harwell Apr 07 '14 at 20:04
  • the poster says waiting/pausing the main thread is not an option. – T McKeown Apr 07 '14 at 20:05
  • 280Z28 - it is what i need! – zzfima Apr 07 '14 at 20:09
  • 1
    @zzfima, you are confusing, first you state no sleep or loops... whatever. – T McKeown Apr 07 '14 at 20:10
  • @TMcKeown I edited the post to describe the use of a `CancellationTokenSource` to support immediate cancellation of concurrent operations. – Sam Harwell Apr 07 '14 at 20:12
  • right, but your code is in a loop. something the poster said he didn't want to do. I want to call him a "more-on" and a waste of time – T McKeown Apr 07 '14 at 20:14
  • this is from his post: `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.` – T McKeown Apr 07 '14 at 20:15
0

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.

Darryl
  • 5,907
  • 1
  • 25
  • 36