TPL 数据流块中抛出的异常方法名称始终为 MoveNext()
Exception method name thrown in TPL Dataflow block is always MoveNext()
我试图在下面的示例中获取异常堆栈跟踪的最内部方法名称。由于未知原因,我总是得到 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
更新:
在 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
。堆栈跟踪:
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 的第一个字符串)。
这个:
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
作为方法名称的原因。
要解决您在 答案中解释的问题,请通过正则表达式从异常堆栈跟踪中获取名称:
new Regex(@"\<(.*?)\>").Match(myException.StackTrace).ToString().Trim('>','<');
而不是
myException.TargetSite.Name.ToString()
我试图在下面的示例中获取异常堆栈跟踪的最内部方法名称。由于未知原因,我总是得到 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
更新:
在 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
。堆栈跟踪:
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 的第一个字符串)。
这个:
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
作为方法名称的原因。
要解决您在
new Regex(@"\<(.*?)\>").Match(myException.StackTrace).ToString().Trim('>','<');
而不是
myException.TargetSite.Name.ToString()