1. ホーム
  2. c#

.NETの非同期メソッドで良いスタックトレースを取得することは可能ですか?

2023-09-22 23:41:24

質問

WebApiアプリケーションに以下のようなサンプルコードを設定しています。

[HttpGet]
public double GetValueAction()
{
    return this.GetValue().Result;
}

public async Task<double> GetValue()
{
    return await this.GetValue2().ConfigureAwait(false);
}

public async Task<double> GetValue2()
{
    throw new InvalidOperationException("Couldn't get value!");
}

悲しいかな、GetValueActionがヒットしたときに返ってくるスタックトレースは。

    " at MyProject.Controllers.ValuesController.<GetValue2>d__3.MoveNext() in c:\dev\MyProject\MyProject\Controllers\ValuesController.cs:line 61 --- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at MyProject.Controllers.ValuesController.<GetValue>d__0.MoveNext() in c:\dev\MyProject\MyProject\Controllers\ValuesController.cs:line 56"

したがって、私はトレースで(混乱した)GetValue2とGetValueを得るが、GetValueActionの言及はない。私は何か間違っているのでしょうか?私にもっと完全なスタックトレースを取得する別のパターンがありますか?

EDIT: 私の目標は、スタックトレースに依存したコードを書くことではなく、非同期メソッドでの失敗をデバッグしやすくすることです。

どのように解決するのですか?

この質問と最も投票された回答は、2013年に書かれました。それ以来、状況は改善されています。

.NET Core 2.1では、箱から出してすぐに分かりやすい非同期スタックトレースを提供するようになりました。 .NET Core 2.1 でのスタック トレースの改善点 .

まだ .NET Framework を使用している人のために、スタック トレースの非同期 (および他の多くの不明瞭な点) を修正する優れた NuGet パッケージがあります。 Ben.Demystifier . 他の提案に対するこのパッケージの利点は、スローするコードやアセンブリに変更を加える必要がないことです; あなたは、単に Demystify または ToStringDemystified を追加してください。

これを自分のコードに適用する。

System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: Couldn't get value!
   at async Task<double> ValuesController.GetValue2()
   at async Task<double> ValuesController.GetValue()
   --- End of inner exception stack trace ---
   at void System.Threading.Tasks.Task.ThrowIfExceptional(bool includeTaskCanceledExceptions)
   at TResult System.Threading.Tasks.Task<TResult>.GetResultCore(bool waitCompletionNotification)
   at TResult System.Threading.Tasks.Task<TResult>.get_Result()
   at double ValuesController.GetValueAction()
   at void Program.Main(string[] args)
---> (Inner Exception #0) System.InvalidOperationException: Couldn't get value!
   at async Task<double> ValuesController.GetValue2()
   at async Task<double> ValuesController.GetValue()<---

これは、あなたが Task<T>.Result . もし、あなたの GetValueAction メソッドを非同期化すると ( async all the way の精神で)、期待通りのきれいな結果が得られるでしょう。

System.InvalidOperationException: Couldn't get value!
   at async Task<double> ValuesController.GetValue2()
   at async Task<double> ValuesController.GetValue()
   at async Task<double> ValuesController.GetValueAction()