スタックをオーバーフローさせることなく、非同期関数を再帰的に呼び出すことはできますか?

Rollie

async関数のリターンサイトは呼び出し元ではないので、これは機能すると思いますが、念のためこれが安全であることを確認したいと思いました。そうでない場合、なぜこれがスタックをオーバーフローさせるのでしょうか?

static async Task CheckAsync(TimeSpan recursiveTimer)
{
    // do some work

    await Task.Delay(recursiveTimer);
    CheckAsync(recursiveTimer);
}

編集:私はそれを試してみることにしました-それはスタックをオーバーフローしていないようです(それは今私のマシンで実行されています-それは現在210,000を呼び出しています)。私が推測した理由は、CheckAsync関数の戻りサイトが実際にはCheckAsyncではなく、非同期配管のどこかにあるためです。したがって、CheckAsyncがCheckAsyncを呼び出すとき、実際には通常の関数呼び出しメカニズムを介して呼び出しスタックに追加されるのではなく、非同期関数を管理する他のスレッドを介して実行される非同期の「実行される」キューに関数をオブジェクトとして配置します。

このメカニズムをよく知っている人には、これは正しいと思いますか?

ジョンスキート

それがあなたのために働いている理由は、CheckAsync呼ばれる方法のためではなく、あなたがの結果を待っているからですTask.Delayそれは常に「まだ完了していない」タスクを返すので、それを待つと継続がスケジュールされます。その継続は事実上空のスタックで実行されるため、再帰呼び出しを行うことは重要ではありません。

さて、IIRCフレームワークはどんどん大きくなる「論理スタック」を追跡するので、まだ効果的にメモリリークがあると思います...しかし、それはヒープに保存され、不足するまで拡張されますメモリ。

スタックが爆発するのを見たい場合は、コードを次のように変更するだけです。

static async Task CheckAsync(TimeSpan recursiveTimer)
{
    // Whatever
    await Task.FromResult(5);
    CheckAsync(recursiveTimer);
}

その時点で、「whatever」のコードが何も待たないと仮定するTaskと、完了と例外を追跡するために使用するだけで、完全に同期したコードになります。

これを繰り返し作業を行うためのパターンとしてはお勧めしませんが(前述のメモリリークのせいもあります)、スタックオーバーフローが発生しない理由を説明できると思います。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

bash関数がローカル変数を使用せずに自分自身を再帰的に呼び出すことができるのはなぜですか?

分類Dev

適切に実装された再帰的なレイジーイテレータ関数は、スタックオーバーフローを起こすことはありませんか?

分類Dev

asyncは呼び出し元に雪だるま式になり、コンストラクターを非同期にすることはできません

分類Dev

オーバーロード演算子関数で「等しい」を呼び出すことはできませんか?

分類Dev

コンストラクターまたはinitブロックから呼び出されたオーバーライドされた抽象関数で変数を初期化するときに変数が正しく初期化されない

分類Dev

再帰ループに入ることなく、親クラスの関数を適切に呼び出す

分類Dev

phpクラスからグローバル関数を呼び出すことはできません

分類Dev

Flutterは別のクラスから非同期関数を呼び出すことはできません

分類Dev

Javascriptの再帰的な非同期関数がスタックオーバーフローにつながるのはなぜですか?

分類Dev

誤解を招く「コールバックなしで非同期関数を呼び出すことは非推奨です」警告

分類Dev

再帰関数は、定数をパラメーターとして送信せずに、最初に呼び出された関数の定数を知ることができますか?

分類Dev

関数を呼び出すオーバーヘッドなしに、リスト内包内から関数を呼び出すことは可能ですか?

分類Dev

非同期コードを呼び出すときに、AggregateExceptionsで複数の例外を常に考慮することは理にかなっていますか?

分類Dev

AngularJs:「controlleras」構文-データにアクセスすることはできませんが、関数を呼び出すことはできません

分類Dev

ステータスバーへの通知を非同期タスクから呼び出すことはできますか

分類Dev

TcpClientからデータを受信するときに、非同期メソッドと長時間実行タスクを再帰的に呼び出す

分類Dev

Androidでスタックオーバーフローエラーを引き起こす再帰呼び出しを解決するにはどうすればよいですか?

分類Dev

非同期関数をクラスフィールドに含めることはできますか?

分類Dev

異なるパラメーターを持つ関数がローカルで定義されている場合、静的にインポートされたオーバーロードされた関数を呼び出すことはできませんか?

分類Dev

Javascriptで関数をグローバルに呼び出すことができるのに、なぜコールバックを使用するのですか?

分類Dev

Cythonはこの関数のPythonメソッド呼び出しのオーバーヘッドをさらに減らすことができますか?

分類Dev

Cの再帰関数がスタックオーバーフローを引き起こすのはなぜですか?

分類Dev

Kotlinでは、ディスパッチ先のオブジェクトとレシーバーの両方を指定するメンバー拡張関数を呼び出すことはできますか?もしそうなら、どのように?

分類Dev

DeprecationWarning:コールバックなしで非同期関数を呼び出すことは非推奨です。-「関数:」がどこにあるかを見つけるには?

分類Dev

コールバックを呼び出す前に、非同期で作成されたオブジェクトが完全に使用可能になるのをどのように待つことができますか?

分類Dev

コンストラクタでこの関数を呼び出すと、スタックオーバーフローエラーが発生するのはなぜですか?

分類Dev

この再帰関数を修正して、呼び出しが深くならないようにすることはできますか?

分類Dev

スーパークラスのオーバーライドされたセッタープロパティを呼び出すことができません

分類Dev

コンストラクターの子型から関数を呼び出すことはできません

Related 関連記事

  1. 1

    bash関数がローカル変数を使用せずに自分自身を再帰的に呼び出すことができるのはなぜですか?

  2. 2

    適切に実装された再帰的なレイジーイテレータ関数は、スタックオーバーフローを起こすことはありませんか?

  3. 3

    asyncは呼び出し元に雪だるま式になり、コンストラクターを非同期にすることはできません

  4. 4

    オーバーロード演算子関数で「等しい」を呼び出すことはできませんか?

  5. 5

    コンストラクターまたはinitブロックから呼び出されたオーバーライドされた抽象関数で変数を初期化するときに変数が正しく初期化されない

  6. 6

    再帰ループに入ることなく、親クラスの関数を適切に呼び出す

  7. 7

    phpクラスからグローバル関数を呼び出すことはできません

  8. 8

    Flutterは別のクラスから非同期関数を呼び出すことはできません

  9. 9

    Javascriptの再帰的な非同期関数がスタックオーバーフローにつながるのはなぜですか?

  10. 10

    誤解を招く「コールバックなしで非同期関数を呼び出すことは非推奨です」警告

  11. 11

    再帰関数は、定数をパラメーターとして送信せずに、最初に呼び出された関数の定数を知ることができますか?

  12. 12

    関数を呼び出すオーバーヘッドなしに、リスト内包内から関数を呼び出すことは可能ですか?

  13. 13

    非同期コードを呼び出すときに、AggregateExceptionsで複数の例外を常に考慮することは理にかなっていますか?

  14. 14

    AngularJs:「controlleras」構文-データにアクセスすることはできませんが、関数を呼び出すことはできません

  15. 15

    ステータスバーへの通知を非同期タスクから呼び出すことはできますか

  16. 16

    TcpClientからデータを受信するときに、非同期メソッドと長時間実行タスクを再帰的に呼び出す

  17. 17

    Androidでスタックオーバーフローエラーを引き起こす再帰呼び出しを解決するにはどうすればよいですか?

  18. 18

    非同期関数をクラスフィールドに含めることはできますか?

  19. 19

    異なるパラメーターを持つ関数がローカルで定義されている場合、静的にインポートされたオーバーロードされた関数を呼び出すことはできませんか?

  20. 20

    Javascriptで関数をグローバルに呼び出すことができるのに、なぜコールバックを使用するのですか?

  21. 21

    Cythonはこの関数のPythonメソッド呼び出しのオーバーヘッドをさらに減らすことができますか?

  22. 22

    Cの再帰関数がスタックオーバーフローを引き起こすのはなぜですか?

  23. 23

    Kotlinでは、ディスパッチ先のオブジェクトとレシーバーの両方を指定するメンバー拡張関数を呼び出すことはできますか?もしそうなら、どのように?

  24. 24

    DeprecationWarning:コールバックなしで非同期関数を呼び出すことは非推奨です。-「関数:」がどこにあるかを見つけるには?

  25. 25

    コールバックを呼び出す前に、非同期で作成されたオブジェクトが完全に使用可能になるのをどのように待つことができますか?

  26. 26

    コンストラクタでこの関数を呼び出すと、スタックオーバーフローエラーが発生するのはなぜですか?

  27. 27

    この再帰関数を修正して、呼び出しが深くならないようにすることはできますか?

  28. 28

    スーパークラスのオーバーライドされたセッタープロパティを呼び出すことができません

  29. 29

    コンストラクターの子型から関数を呼び出すことはできません

ホットタグ

アーカイブ