相关疑难解决方法(0)

调用堆栈没有说"你来自哪里",而是"你下一步去哪里"?

在上一个问题(获取对象调用层次结构)中,我得到了这个有趣的答案:

调用堆栈不是告诉你你来自哪里.它是告诉你下一步的去向.

据我所知,当到达函数调用时,程序通常会执行以下操作:

  1. 调用代码时:

    • 存储返回地址(在调用堆栈上)
    • 保存寄存器的状态(在调用堆栈上)
    • 写入将传递给函数的参数(在调用堆栈或寄存器中)
    • 跳转到目标函数

  2. 被叫目标代码中:

    • 检索存储的变量(如果需要)

  3. 返回过程:撤消我们调用函数时所做的操作,即展开/弹出调用堆栈:

    • 从调用堆栈中删除局部变量
    • 从调用堆栈中删除函数变量
    • 恢复寄存器状态(我们之前存储的状态)
    • 跳转到返回地址(我们之前存储的地址)

题:

如何将其视为"告诉您下一步的去向"而不是"告诉您从何而来"

在C#的JIT或C#的运行时环境中是否存在使得调用堆栈以不同方式工作的东西?

感谢有关调用堆栈描述的文档的任何指示 - 有大量关于传统调用堆栈如何工作的文档.

.net c# callstack

15
推荐指数
2
解决办法
2045
查看次数

如何找到哪种方法在异步/等待中“挂起”?

在过去,跟踪挂起的方法非常容易:只需转到调试器,单击“暂停”按钮并遍历堆栈跟踪即可。

但是,现在,如果问题出在异步方法中,则该方法不起作用-因为要执行的下一段代码埋在连续任务中的某个位置(从技术上讲,它甚至都没有挂起)...轻松调试任务?

UPD。

例:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();           
    }

    private async void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        await DoHolyWar();
        MessageBox.Show("Holy war complete!");
    }

    public static async Task DoHolyWar()
    {
        await DoHolyWarComplicatedDetails();
        Console.WriteLine("Victory!");
    }

    public static async Task DoHolyWarComplicatedDetails()
    {
        await BurnHeretics();
    }

    public static Task BurnHeretics()
    {
        var tcs = new TaskCompletionSource<object>();

        // we should have done this, but we forgot
        // tcs.SetResult(null);

        return tcs.Task;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果启动它并单击“暂停”,则只会看到DoHolyWar方法正在挂起,但看不到确切的位置。如果您用.Wait()替换'await',然后执行相同的操作,则可以检查挂起的堆栈跟踪。通过此示例,它非常简单,但是在实际应用中,通常很难找到问题所在。特别是,桌面应用程序将在主线程上运行事件循环,因此,即使某些事情“挂起”,而您单击“暂停”,也不会知道出了什么问题。

c# debugging asynchronous task hang

5
推荐指数
1
解决办法
937
查看次数

标签 统计

c# ×2

.net ×1

asynchronous ×1

callstack ×1

debugging ×1

hang ×1

task ×1