.net - 为什么 Visual Studio 调试器不显示由 wait 关键字生成的状态机代码?

标签 .net visual-studio async-await visual-studio-2015

当我在正在等待的方法主体中设置断点时,Visual Studio 调试器显示一个调用堆栈,其中没有任何 C# 编译器生成的代码。

请看下图,这是我简单的async方法和调用堆栈。

enter image description here

请注意,没有调用 MoveNext或初始化状态机对象或TaskAwaiter<TResult>AsyncTaskOfTMethodBuilder在调用堆栈中。

为什么会这样呢?就像 IL Spy 中一样,Visual Studio 中是否有一些设置可以切换,使其在调试 session 正在进行时在调用堆栈和编辑器中显示状态机代码?

我突然想起有一个DebuggerStepThroughAttribute在重写的按钮上单击实例化状态机的处理程序代码。但我不确定这是否是它对调试器隐藏的原因。难道这不应该只是将调用堆栈中编译器生成的方法的堆栈框架变灰吗?

不是 DebuggerHiddenAttribute使代码对调试器不可见的那个?

最佳答案

这里有几件事需要注意。

首先,您有 2 个线程正在运行:

  1. 主线程,运行消息泵并拥有包含按钮的窗口
  2. 正在运行任务的线程

一个线程内的调用堆栈绝不会反射(reflect)创建它的线程当前正在执行的操作。

如果您检查可以在调试器中显示所有线程及其调用堆栈的调试器 Pane ,您最多会看到两个线程及其调用堆栈。

但是,如果调试器命中断点时执行此方法的线程仍在该方法中,则这只会显示按钮事件处理程序。由于启动新线程的开销,这很可能不是真的。

原因是 async/await 当它遇到 await 时,async 方法返回 。当单独的线程开始执行您的委托(delegate)时,按钮事件处理程序方法很可能已经返回。

即使您手动为委托(delegate)启动一个线程并加入(等待)该线程,您也不会在调用堆栈中看到它,但您绝对应该在其他调试器中看到它线程及其调用堆栈的 Pane 。

关于.net - 为什么 Visual Studio 调试器不显示由 wait 关键字生成的状态机代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37665700/

相关文章:

.net - 制作 Uri 对象的最通用方法?

c# - 如何配置 Visual Studio 2017 以在 ASP.Net MVC https 站点中公开非加密端口

c# - ConfigureAwait(false) 和 IAsyncDisposable 的结构实现

c# - 如何使正则表达式适用于角落案例电子邮件地址

java - 如何连接到 Web 服务(启用 SSL 和代理接口(interface))

c# - 字典的反序列化问题

windows - Visual Studio 2019 路径中的非法字符

c# - 获取解决方案中的所有启动项目

node.js - 通过管道将 axios 请求发送到 pkgcloud 存储上传会导致 "write after end"错误

javascript - 如何用 Jest 测试异步等待 pg 连接?