2015-07-12 163 views
1

我试图在下面的示例中获取大多数异常堆栈跟踪的内部方法名称。由于不明原因,我总是得到MoveNext方法名称,而不是真名。我该如何解决它?在TPL数据流块中抛出的异常方法名始终是MoveNext()

var st = new StackTrace(ex, true); 
var frame = st.GetFrames()?.First(y => y.GetFileName() != null); 
var method = frame.GetMethod().ToString(); // result: Void MoveNext() 
var method2 = frame.Name; // result: MoveNext 

UPDATE:

这时候,异常的TPL Dataflow块的委托抛出发生:

private async Task Parse(ListItem item) 
{ 
    await Task.Delay(1); 
    throw new Exception("Error"); 
} 

// ...

var parseBlock = new ActionBlock<ListItem>(
        async x => { await Parse(x).ConfigureAwait(false); }); 

我得到MoveNext从与任何代表任何块。 Stacktrace:

at RP.Core.ListsPipeline.<Parse>d__21.MoveNext() in Class.cs:line 179 
--- 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.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult() 
at Class.<<Start>b__18_0>d.MoveNext() in Class.cs:line 81 

我想要得到Parse方法名称(StackTrace的第一个字符串)。

+0

向我们展示触发异常的代码。 –

+0

发布的代码是“如何获得例外信息”,是不必要的。 –

+0

同时发布确切的异常细节(从调试器窗口)。 –

回答

3

此:

private async Task Parse(ListItem item) 
{ 
    await Task.Delay(1); 
    throw new Exception("Error"); 
} 

被翻译成这样:

private Task Parse() 
{ 
    Program.<Parse>d__0 <Parse>d__; 
    <Parse>d__.<>t__builder = AsyncTaskMethodBuilder.Create(); 
    <Parse>d__.<>1__state = -1; 
    AsyncTaskMethodBuilder <>t__builder = <Parse>d__.<>t__builder; 
    <>t__builder.Start<Program.<Parse>d__0>(ref <Parse>d__); 
    return <Parse>d__.<>t__builder.Task; 
} 

和你的方法的实际调用是状态机的编译器创建MoveNext()方法内。这实际上意味着代码不在Parse()内部调用。这就是为什么你看到MoveNext作为方法名称,这就是为什么你将不能得到Parse作为方法名称。