当我在我正在等待的方法体中设置断点时,Visual Studio调试器显示一个没有任何C#编译器生成代码的调用堆栈。
请查看下面的图片,其中显示了我的简单async
方法和调用堆栈。
请注意,没有调用MoveNext
或初始化状态机对象或调用堆栈中的TaskAwaiter<TResult>
或AsyncTaskOfTMethodBuilder
。
为什么会这样?就像在IL Spy中一样,Visual Studio中是否有一些设置可以切换,以便在调试会话正在进行时在调用堆栈和编辑器中显示状态机代码?
我突然想起重写的按钮点击处理程序代码上有一个DebuggerStepThroughAttribute
来实例化状态机。但我不确定这是否是它从调试器中隐藏的原因。这个不应该只是灰色了调用堆栈中编译器生成的方法的堆栈帧吗?
DebuggerHiddenAttribute
不是使代码对调试器不可见的那个吗?
答案 0 :(得分:2)
这里有几点需要注意。
首先,你有2个线程在玩:
一个线程内的调用堆栈决不会反映创建它的线程当前正在做什么。
如果你检查可以在调试器中显示所有线程及其callstack的调试器窗格,你最多会看到两个线程及其callstack。
但是,这只会显示按钮事件处理程序,如果执行此方法的线程在调试器遇到断点时仍在方法中。由于旋转新线程的开销,这很可能不正确。
原因是async/await
在遇到async
时await
方法返回。当单独的线程开始执行您的委托时,按钮事件处理程序方法很可能已返回。
即使你手动为你的委托启动一个线程并加入(等待)该线程,你也不会在 callstack 中看到这个,但是你应该在其他调试器中看到它线程及其调用栈的窗格。