Reputation: 1565
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
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
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