【问题标题】:Exception method name thrown in TPL Dataflow block is always MoveNext()TPL Dataflow 块中抛出的异常方法名称始终为 MoveNext()
【发布时间】:2015-09-30 19:30:02
【问题描述】:

我正在尝试在下面的示例中获取异常堆栈跟踪的最内部方法名称。由于未知原因,我总是得到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 Block 的委托中抛出异常时会发生这种情况:

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 的第一个字符串)。

【问题讨论】:

  • 向我们展示触发异常的代码。
  • 贴出的代码是“如何获取异常信息”,没有必要。
  • 还发布确切的异常详细信息(来自调试器窗口)。
  • 你已经得到了名字,至少是 async/await 转换给你留下的名字。您的方法已成为“状态机”(一个类),而 MoveNext() 是它的主要方法。
  • 当然有,用一些简单的正则表达式。

标签: c# exception methods async-await task-parallel-library


【解决方案1】:

这个:

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 作为方法名称的原因。

【讨论】:

    【解决方案2】:

    要解决您在this 答案中解释的问题,请通过正则表达式从异常堆栈跟踪中获取名称:

    new Regex(@"\&lt;(.*?)\&gt;").Match(myException.StackTrace).ToString().Trim('&gt;','&lt;');

    而不是

    myException.TargetSite.Name.ToString()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-16
      • 2015-09-23
      • 2018-05-19
      • 1970-01-01
      • 2011-12-24
      相关资源
      最近更新 更多