Rub*_*ink 6 asynchronous exception-handling task-parallel-library c#-4.0
我有一个返回任务的Async方法.
我也希望提供同步等效,但我不希望它的消费者必须去解包AggregateException.
现在我明白了整个想法是你不能随意选择一个,我知道我可以阅读更多的Stephen Toub文章(我会,但不是现在),我会理解这一切,并且可以自己决定.
在此期间,我想使用这样一个事实:我的任务实际上只是没有并行性的链接"工作流程",只是干预Waits(不,不是TPL DataFlow),这不应该导致多个异常.在这种情况下,处理如下是适当的:
CallAsync().Wait();
}
catch( AggregateException ae)
{
throw ae.Flatten().First()
Run Code Online (Sandbox Code Playgroud)
或者我保证即使有不止一个也AggregateException总是有InnerException.还是有一种情况我应该回归.Flatten().First()?
在一些TPL文档中,我看到了对Unwrap()方法的引用AggregateException(不确定它是否是扩展或beta版本中的某些内容).
作为占位符,我正在做:
void Call( )
{
try
{
CallAsync().Wait();
}
catch ( AggregateException ex )
{
var translated = ex.InnerException ?? ex.Flatten().InnerExceptions.First();
if ( translated == null )
throw;
throw translated; }
}
Task CallAsync(){ ...
Run Code Online (Sandbox Code Playgroud)
Dre*_*rsh 21
我知道,没有"干净"的方法来做到这一点.你不能使用,throw someInnerException;因为你会在异步工作流中的异常发生地丢失堆栈,如果你只是使用throw;你显然会传播它AggregateException.你需要为同步方法做些什么是有一些"包装"异常,你可以填充AggregateExceptioninto 的第一个异常,然后从方法的同步版本中一致地抛出它.
void Call()
{
try
{
CallAsync().Wait();
}
catch (AggregateException ex)
{
throw new MyConsistentWrapperException("An exception occurred while executing my workflow. Check the inner exception for more details.", ex.Flatten().InnerExceptions.First());
}
}
Run Code Online (Sandbox Code Playgroud)
FWIW,他们已经在4.5中使用新ExceptionDispatchInfo类解决了这个问题,它将帮助您跨线程编组异常而不会破坏堆栈.然后你可以写这样的同步版本:
void Call()
{
try
{
CallAsync().Wait();
}
catch (AggregateException ex)
{
ExceptionDispatchInfo.Capture(ex.Flatten().InnerExceptions.First()).Throw();
}
}
Run Code Online (Sandbox Code Playgroud)