在上一个问题(获取对象调用层次结构)中,我得到了这个有趣的答案:
调用堆栈不是告诉你你来自哪里.它是告诉你下一步的去向.
据我所知,当到达函数调用时,程序通常会执行以下操作:
在调用代码时:
在被叫目标代码中:
返回过程:撤消我们调用函数时所做的操作,即展开/弹出调用堆栈:
题:
如何将其视为"告诉您下一步的去向"而不是"告诉您从何而来"?
在C#的JIT或C#的运行时环境中是否存在使得调用堆栈以不同方式工作的东西?
感谢有关调用堆栈描述的文档的任何指示 - 有大量关于传统调用堆栈如何工作的文档.
在过去,跟踪挂起的方法非常容易:只需转到调试器,单击“暂停”按钮并遍历堆栈跟踪即可。
但是,现在,如果问题出在异步方法中,则该方法不起作用-因为要执行的下一段代码埋在连续任务中的某个位置(从技术上讲,它甚至都没有挂起)...轻松调试任务?
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',然后执行相同的操作,则可以检查挂起的堆栈跟踪。通过此示例,它非常简单,但是在实际应用中,通常很难找到问题所在。特别是,桌面应用程序将在主线程上运行事件循环,因此,即使某些事情“挂起”,而您单击“暂停”,也不会知道出了什么问题。