在恢复C#异步方法时,System.Diagnostics.StackTrace中缺少Visual Studio 2017调用堆栈中可见的堆栈帧
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在恢复C#异步方法时,System.Diagnostics.StackTrace中缺少Visual Studio 2017调用堆栈中可见的堆栈帧相关的知识,希望对你有一定的参考价值。
我有以下使用asyc方法的简单C#代码片段:
class SUT
{
public async Task<int> GetValue()
{
await Task.Delay(1000);
return 42;
}
}
class Program
{
static async Task<int> CallAsync()
{
SUT sut = new SUT();
int result = await sut.GetValue();
return result;
}
static void Main(string[] args)
{
CallAsync().GetAwaiter().GetResult();
}
}
我将断点放在“return 42”语句中,并观察Visual Studio Call Stack和从System.Diagnostics.StackTrace()获得的StackTrace。在VS Call Stack窗口中可以看到一些未在StackTrace中显示的帧,如下图所示:StackTrace is missing frames from VS Call Stack window
有没有办法使用System.Diagnostics.StackTrace完全按照在Visual Studio调用堆栈窗口中观察到的方式获取堆栈跟踪?
好吧,如果你考虑堆栈跟踪是什么,它就是一堆被称为方法的文件。最深层的方法位于堆栈顶部。如果你考虑以下程序,Main调用第一个,第一个调用第二个,第二个调用第三个。
class Program
{
static void Main(string[] args) => First();
static void First() => Second();
static void Second() => Third();
static void Third() => Console.WriteLine("Third method.");
}
当你进入Third方法时,你的堆栈将如下所示(左边是堆栈的顶部):
Third - Second - First - Main
然后当第三个完成时,第三个从堆栈中弹出,跟踪如下所示:
Second - First - Main
等等等等
现在,当没有涉及异步代码时,这很容易理解。那么让我们看看你的例子中发生了什么:
static void Main(string[] args) => First().Wait();
static async Task First()
{
Console.WriteLine("First method starting");
await Task.Delay(1000);
Console.WriteLine("First method finishing.");
}
当你在First
方法的第一行中放置一个断点时,callstack与上面类似,因为代码同步执行到那一点。但是,该方法实际上在调用await Task.Delay
时返回,从堆栈中弹出First
方法。在此之后可以访问第三行的唯一方法是框架在第三行创建“延续”。现在可能很清楚,这个延续必须由我们自己的代码以外的东西调用,这就是callstack包含所有这些奇怪方法的原因。
因此,您无法获得仅包含代码的callstack,因为它不再存在,但在Visual Studio设置中,您可以启用Just My Code。当您在上一个示例中的First
方法的第3行中断时,这可能看起来像这样。不完全是你想要的,但接近。
(来自VSCode的截图)
以上是关于在恢复C#异步方法时,System.Diagnostics.StackTrace中缺少Visual Studio 2017调用堆栈中可见的堆栈帧的主要内容,如果未能解决你的问题,请参考以下文章