在「舊」時代,很容易跟蹤哪種方法掛起:只需進入調試器,點擊「暫停」按鈕並瀏覽堆棧跟蹤。如何找到哪個方法與異步/等待掛起?
現在,如果問題出在異步方法中,這種方法不起作用 - 因爲下一段要執行的代碼被埋在繼續任務的某處(從技術上說,它甚至不會掛起)......是一個簡單的調試任務的方法?
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;
}
}
請注意,如果你一開始它並點擊「暫停」,你將只能看到DoHolyWar方法是掛,但你不會看到哪兒。而如果用.Wait()替換'await',並執行相同的操作,則可以檢查掛起的堆棧跟蹤。這個例子很簡單,但在真實世界的應用程序中,通常很難找到問題。特別是桌面應用程序將在主線程上運行事件循環,因此即使某些事情「掛起」,並且您點擊「暫停」,您也不會知道哪裏出了問題。
作爲一般規則,它幾乎總是試圖通過顯式調用「Wait」或「Result」來嘗試行爲,就像異步不存在一樣。 –
啊,好的。所以它不是一個真正的「掛起」,因爲你的程序仍然是響應式的(如果你已經完成了WPF或winforms程序並且執行了「等待DoHolyWar()」程序仍然會響應,你可能想要改變你的問題做而不是作爲一個控制檯應用程序來使它更清楚你不是在談論實際的「掛起」),而是發現'SetResult'永遠不會被調用。 –
事實上,我更新了你的問題來做到這一點,如果你不喜歡它可以隨時回滾更改。 –