.NET の yield
と await
の制御フロー メカニズム
.NET の yield
および await
キーワードについての理解は、通常は正しいです。 yield
イテレータ ブロックが呼び出しコードに制御を返し、イテレータが再度呼び出されたときに中断したところから実行を再開できるようにします。 await
呼び出し先が完了するのを待つだけでなく、呼び出し元に制御を返します。呼び出し元がメソッドを再度 await
すると、実行は中断したところから再開されます。
これらの構造を理解する鍵は、その実装メカニズムにあります。 await
の場合、それは本質的に「高レベルのリターン」に相当します。 await
式が検出されると、ランタイムはタスクが完了したかどうかを確認します。完了していない場合は、デリゲートを割り当て、タスクの継続としてメソッドの残りの部分を実行し、それを呼び出し元に返します。タスクが完了すると、メソッドの残りの部分がすぐに実行されます。
await
の継続には、ルックアップ テーブル内で実行される次の命令ポインターを識別する番号が含まれます。これにより、タスクが再開されたときに、正しい場所から実行を継続できるようになります。継続ではすべてのローカル変数と一時変数の値も保存されるため、メソッドは中断されなかったかのように実行を再開できます。
await
の前にランタイムが複数のメソッド呼び出しをどのように処理するかという質問については、呼び出し元のアクティベーション レコードと呼び出し元のメソッドのアクティベーション レコードは同じスタックに格納されない、というのが答えです。代わりに、await
リカバリに関連する情報がヒープに保存されます。これにより、後続のメソッド呼び出しによってスタックが上書きされなくなります。
未処理の例外が発生した場合、その例外は捕捉され、タスクに保存されます。この例外は、タスクの結果が取得されたときに再スローされます。この動作により、非同期操作が存在する場合でも例外が正しく処理されることが保証されます。
同様の原則が yield
の実装にも適用されます。イテレータが値を yield
ブロックすると、次回イテレータが呼び出されたときに実行を再開する必要がある MoveNext
命令を示す番号とともに、ローカル変数の状態がヒープにコピーされます。これにより、反復子は yield
ポイントで実行を一時停止し、後で状態を失うことなく実行を再開できます。
これらの複雑なメカニズムを活用することで、yield
および await
キーワードは、.NET で非同期および反復操作を実装する強力な方法を提供します。これらにより、スレッドを必要とせずに同時実行性をシミュレートし、コードを簡素化し、パフォーマンスを向上させることができます。
以上が「yield」と「await」は .NET で制御フローをどのように管理しますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。