我正在使用TPL Dataflow库中的TransformBlock,我意识到在转换过程中抛出异常时,我会在" Receive"中得到一个通用异常。方法,但没有提到原来的。
在此代码中:
Func<Int32, Task<String>> transformer = async i => { await Task.Yield(); throw new ArgumentException("whatever error"); };
TransformBlock<Int32, String> transform = new TransformBlock<int, string>(transformer);
transform.Post(1);
try
{
var x = await transform.ReceiveAsync();
}
catch (Exception ex)
{
// catch
}
例外ex
包含:
System.InvalidOperationException was caught
HResult=-2146233079
Message=The source completed without providing data to receive.
Source=System.Threading.Tasks.Dataflow
StackTrace:
at System.Threading.Tasks.Dataflow.Internal.Common.InitializeStackTrace(Exception exception)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at DoubleQueueTest.Program.<testwhatever>d__5.MoveNext() in c:\Users\vtortola\Documents\Visual Studio 2013\Projects\DoubleQueueTest\DoubleQueueTest\Program.cs:line 43
InnerException:
不提及原始异常类型或其消息。有没有办法强迫它抛出原来的?或者至少使用它作为内部例外?
答案 0 :(得分:5)
您正在查看ReceiveAsync
的例外情况。 InvalidOperationException
是预期的行为。
如果要检测或响应阻止故障,请await
IDataflowBlock.Completion
属性。
答案 1 :(得分:0)
我正在添加此响应仅用于完成。正如@Stephen清楚地指出的那样,如果其中一个项目出现故障,转换将会出错。因此,如果您的转换因单个项目出错而无法停止,我使用了这种方法:
创建一个代表操作结果的小类:
class TransformResult<T>
{
public T Result { get; set; }
public ExceptionDispatchInfo Error { get; set; }
}
如果有异常,请捕获并返回结果:
Func<Int32, Task<TransformResult<String>>> transformer = async i =>
{
await Task.Yield();
try
{
// do whatever
throw new ArgumentException("whatever error");
}
catch (Exception ex)
{
return new TransformResult<String>() { Error = ExceptionDispatchInfo.Capture(ex) };
}
};
等待转换结果时,如果结果包含错误...抛出它:
var transform = new TransformBlock<int, TransformResult<String>>(transformer);
transform.Post(1);
try
{
var x = await transform.ReceiveAsync();
if (x.Error != null)
x.Error.Throw();
}
catch (Exception ex)
{
// catch
}