恢复 C# 异步方法时,System.Diagnostics.StackTrace 中缺少 Visual Studio 2017 调用堆栈中可见的堆栈帧

Posted

技术标签:

【中文标题】恢复 C# 异步方法时,System.Diagnostics.StackTrace 中缺少 Visual Studio 2017 调用堆栈中可见的堆栈帧【英文标题】:Stack frames visible in Visual Studio 2017 Call Stack are missing in System.Diagnostics.StackTrace when resuming C# async method 【发布时间】:2019-08-10 21:05:50 【问题描述】:

我有以下使用 asyc 方法的简单 C# 代码 sn-p:

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 调用堆栈和从 System.Diagnostics.StackTrace() 获得的 StackTrace。在 VS 调用堆栈窗口中有一些可见的帧,这些帧没有出现在 StackTrace 中,如下图所示: StackTrace is missing frames from VS Call Stack window

有没有办法使用 System.Diagnostics.StackTrace 完全按照在 Visual Studio 调用堆栈窗口中观察到的方式获取堆栈跟踪?

【问题讨论】:

【参考方案1】:

好吧,如果你想一想堆栈跟踪是什么,它实际上就是一堆被调用的方法。最深的方法位于堆栈顶部。 如果你考虑下面的程序,Main 首先调用,first 调用第二个,second 调用第三个。

class Program

    static void Main(string[] args) => First();
    static void First() => Second();
    static void Second() => Third();
    static void Third() => Console.WriteLine("Third method.");


当您在第三个方法中时,您的堆栈将如下所示(左侧为堆栈顶部):

Third - Second - First - Main

然后当 Third 完成时,Third 会从堆栈中弹出,跟踪如下所示:

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 方法的第一行设置断点时,调用堆栈与上面类似,因为代码同步执行到该点为止。然而,该方法实际上在调用await Task.Delay返回,将First 方法从堆栈中弹出。之后可以访问第三行的唯一方法是框架在第三行创建“延续”。现在可能很清楚,这个延续必须由我们自己的代码以外的其他东西调用,这就是为什么调用堆栈包含所有这些奇怪的方法。

因此您无法获得仅包含您的代码的调用堆栈,因为它不再存在,但在 Visual Studio 设置中,您可以启用Just My Code。当您在上一个示例中的 First 方法的第 3 行中断时,可能看起来像这样。不完全是您正在寻找的东西,但很接近。

(来自 VSCode 的屏幕截图)

【讨论】:

以上是关于恢复 C# 异步方法时,System.Diagnostics.StackTrace 中缺少 Visual Studio 2017 调用堆栈中可见的堆栈帧的主要内容,如果未能解决你的问题,请参考以下文章

C#异步编程概念和使用

C#使用异步操作时的注意要点(翻译)

在恢复C#异步方法时,System.Diagnostics.StackTrace中缺少Visual Studio 2017调用堆栈中可见的堆栈帧

C# 异步编程

C# 异步方法的异常处理

C# 基于事件的异步模式