How to find which method hangs with async / wait?

In the "old" times, it was very easy to track which method was hanging: just go to the debugger, press "pause" and go through the stack trace.

Now, however, if the problem is in the async method, this approach does not work - since the next piece of code to be executed is buried somewhere in the continuation tasks (technically it does not even hang) ... Is there a way for such easy debugging with tasks ?

UPD

Example:

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 at.Wait() , . , . , , , , - "", "" , , .

+4
1

, Windows "" ( "Ctrl+D, K" ).

, .

enter image description here

Duration, , - , . , , .

, await BurnHeretics(); , , - , . , , , await DoHolyWarComplicatedDetails(); , DoHolyWarComplicatedDetails(), BurnHeretics();, , .

. , await BurnHeretics(); , . Task, <DoHolyWarComplicatedDetails>d__3 " DoHolyWarComplicatedDetails, <DoHolyWarComplicatedDetails>d__3 ." <DoHolyWarComplicatedDetails>d__3 - await BurnHeretics();, , , DotPeek, .

[CompilerGenerated]
private sealed class <DoHolyWarComplicatedDetails>d__3 : IAsyncStateMachine
{
  public int <>1__state;
  public AsyncTaskMethodBuilder <>t__builder;
  private TaskAwaiter <>u__1;

  public <DoHolyWarComplicatedDetails>d__3()
  {
    base..ctor();
  }

  void IAsyncStateMachine.MoveNext()
  {
    int num1 = this.<>1__state;
    try
    {
      TaskAwaiter awaiter;
      int num2;
      if (num1 != 0)
      {
        awaiter = MainWindow.BurnHeretics().GetAwaiter();
        if (!awaiter.IsCompleted)
        {
          this.<>1__state = num2 = 0;
          this.<>u__1 = awaiter;
          MainWindow.<DoHolyWarComplicatedDetails>d__3 stateMachine = this;
          this.<>t__builder.AwaitUnsafeOnCompleted<TaskAwaiter, MainWindow.<DoHolyWarComplicatedDetails>d__3>(ref awaiter, ref stateMachine);
          return;
        }
      }
      else
      {
        awaiter = this.<>u__1;
        this.<>u__1 = new TaskAwaiter();
        this.<>1__state = num2 = -1;
      }
      awaiter.GetResult();
      awaiter = new TaskAwaiter();
      Console.WriteLine("Heretics burned");
    }
    catch (Exception ex)
    {
      this.<>1__state = -2;
      this.<>t__builder.SetException(ex);
      return;
    }
    this.<>1__state = -2;
    this.<>t__builder.SetResult();
  }

  [DebuggerHidden]
  void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
  {
  }
}
+1

Source: https://habr.com/ru/post/1651796/


All Articles