我的情况是:
从主线程我启动线程A. 在主线程中有一些(true)运行了很多时间。同时进行时间消耗操作:
static void Main(string[] args)
{
new Thread(Go).Start();
while (true)
{
Thread.Sleep(1000);
}
}
private static void Go()
{
}
如果线程A中出现错误,我希望在主线程中生成异常
我阅读了一些文章,例如这篇文章:catch exception that is thrown in different thread
唯一的答案是:使用共享变量(one of answers)
所以,解决方案:
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;
}
是不可接受的,因为我希望尽快得到例外。不要等待循环循环。例如,如果我在while循环中做饼干,我不想等待下一个循环,当我加热时:当加热器坏了我希望同时在主线程中产生异常。
现在,我无法将委托传递给线程:如果我从线程A调用委托,则无法切换循环,因为它是其他线程。事件也一样。
我该如何处理这个问题?
由于
答案 0 :(得分:1)
实现此目标的最佳方法是使用任务并行库。如果使用TaskCreationOptions.LongRunning
启动任务,将创建一个新线程来执行任务主体。然后,您可以从主线程访问Task<T>.Result
或调用Wait
,异常(如果有)将传播回线程。使用CancellationTokenSource
来支持取消与Go
操作同时执行的其他操作。
在以下示例中,对Thread.Sleep
的调用是占位符,用于特定于应用程序的耗时操作。
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;
}
}
答案 1 :(得分:0)
正如一些相关问题所示,请使用BackgroundWorker。如果工作线程引发异常,它将通过RunWorkerCompleted事件传递给主线程。请参阅http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.runworkercompleted(v=vs.110).aspx。