简体   繁体   English

在恢复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

I have the following simple C# code snippet that uses asyc methods: 我有以下使用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();
    }
}

I place breakpoint on "return 42" statement and observe both Visual Studio Call Stack and the StackTrace obtained from System.Diagnostics.StackTrace(). 我将断点放在“return 42”语句中,并观察Visual Studio Call Stack和从System.Diagnostics.StackTrace()获得的StackTrace。 There are some frames visible in VS Call Stack window that are not presented in the StackTrace as can be seen in the following picture: StackTrace is missing frames from VS Call Stack window 在VS Call Stack窗口中可以看到一些未在StackTrace中显示的帧,如下图所示: StackTrace缺少来自VS Call Stack窗口的帧

Is there a way to get the stack trace using System.Diagnostics.StackTrace exactly as it is observed in Visual Studio Call Stack window? 有没有办法使用System.Diagnostics.StackTrace完全按照在Visual Studio调用堆栈窗口中观察到的方式获取堆栈跟踪?

Well, if you think about what a stacktrace is, it is literaly a stack of called methods. 好吧,如果你考虑堆栈跟踪是什么,它就是一堆被称为方法的文件。 Where the deepest method resides on top of the stack. 最深层的方法位于堆栈顶部。 If you would consider the following program, Main calls first, first calls second, and second calls third. 如果你考虑以下程序,Main调用第一个,第一个调用第二个,第二个调用第三个。

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

}

When you are inside the Third method, your stack will look like this (left being the top of the stack): 当你进入Third方法时,你的堆栈将如下所示(左边是堆栈的顶部):

Third - Second - First - Main

Then when Third is completed, Third is popped off the stack and the trace looks like this: 然后当第三个完成时,第三个从堆栈中弹出,跟踪如下所示:

Second - First - Main

etc. etc. 等等

Now this is easy to follow when no asynchronous code is involved. 现在,当没有涉及异步代码时,这很容易理解。 So let's see what is happening in your example: 那么让我们看看你的例子中发生了什么:

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.");
}

When you put a breakpoint in the first line of the First method, the callstack is similar as above, because the code executed synchronously up to that point. 当您在First方法的第一行中放置断点时,callstack与上面类似,因为代码同步执行到该点。 However, the method actually returns at the call to await Task.Delay , popping the First method off the stack. 但是,该方法实际上在调用时返回 await Task.Delay ,从堆栈弹出First方法。 The only way the third line can be accessed after that is if the framework creates a 'continuation' at the third line. 在此之后可以访问第三行的唯一方法是框架在第三行创建“延续”。 Now it may be clear that this continuation has to be invoked by something other than our own code, and that is why the callstack contains all these strange methods. 现在可能很清楚,这个延续必须由我们自己的代码以外的东西调用,这就是callstack包含所有这些奇怪方法的原因。

So you cannot get a callstack containing only your code, because it no longer exists, but in the Visual Studio settings, you may enable Just My Code . 因此,您无法获得仅包含代码的callstack,因为它不再存在,但在Visual Studio设置中,您可以启用Just My Code That may look like this when you break on line 3 of the First method in the last example. 当您在上一个示例中的First方法的First 3行中断时,这可能看起来像这样。 Not exactly what you are looking for, but close. 不完全是你想要的,但接近。

(Screenshot from VSCode) (来自VSCode的截图)

异步callstack截图

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM