コード内のブレークポイントをステップオーバーすると、デバッガーの奇妙な動作に遭遇しました。
public async Task DoSomeWork()
{
await Task.Run(() => { Thread.Sleep(1000); });
var test = false;
if (test)
{
throw new Exception("Im in IF body!");
}
}
デバッガーがif
本体に入ります。例外が実際にはスローされないが、そのように見えることは注目に値します。したがって、ブレークポイントをに直接配置すると、それを再現することはできませんthrow
。あなたはそれを上に置き、それif
を捕まえるために体に降りなければなりません。同じことが、あらゆる種類の例外インスタンス(null
および明示的)で機能しreturn
、throw
。の代わりでも機能します。
それに加えて、で行を削除しても機能しawait
ます。
このコードスニペットをさまざまなPCから実行しようとしたので、PCの問題は発生しません。また、VSコードのバグだと思って、JetBrainsのRiderで実行しようとしました。同じ結果です。
私はそれが非同期のものであると確信していますが、それが明示的にどのように機能するのですか?
コードは、Visual Studio 2015を使用して、「デバッグ」ビルドで問題を簡単に再現します。をProgram.Main()
呼び出してDoSomeWork().Wait();
、メソッドにブレークポイントを設定し、ステップスルーするだけで、問題を再現できます。
なぜそれが起こるのかというと、これは間違いなく、async
書き直されているメソッドと生成されたデバッグデータベース(.pdb)の組み合わせによるものです。イテレータメソッドと同様に、メソッドに追加async
すると、コンパイラはメソッドをステートマシンに変更します。生成される実際のILは、元のメソッドに少しだけ似ています。つまり、それを見ると、元のコードの主要なコンポーネントを識別できますがswitch
、メソッドが各await
ステートメントで返されるときに何が起こるかを処理する大きなステートメントになり、それぞれの完了とともに再入力されます待望の表現。
プログラムステートメントがにあるように見える場合throw
、それは実際return
にはメソッドの暗黙のステートメントにあります。実行可能ファイルのデバッグデータベースがその行のプログラムステートメントを提供していないだけです。
デバッグするとき、それが起こっているというヒントがあります。if
ステートメントをステップオーバーすると、ステートメントに直接移動することがわかりますthrow
。場合if
のステートメントブロックがされた本当に入力され、次のプログラム文の行は、実際にブロックではなく、プログラム文の開口部のブレースだろう。
たとえばConsole.WriteLine()
、メソッドの最後にaを追加することもできます。これにより、デバッガーに同期するのに十分な情報が提供され、間違った行番号で表示されなくなります。
方法の詳細についてはasync
方法は、コンパイラによって処理され、参照は、新しいC#の非同期機能は、コンパイラで厳密に実装されている、とのリンクがそこには、(トピックに関する記事のJonのシリーズを含む)が得られました。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加