簡體   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

我有以下使用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缺少來自VS Call Stack窗口的幀

有沒有辦法使用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方法的First 3行中斷時,這可能看起來像這樣。 不完全是你想要的,但接近。

(來自VSCode的截圖)

異步callstack截圖

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM