gpt4 book ai didi

c# - 我可以在不溢出堆栈的情况下递归调用异步函数吗?

转载 作者:太空狗 更新时间:2023-10-29 23:07:21 26 4
gpt4 key购买 nike

由于异步函数的返回站点不是调用者,我假设这是可行的,但我认为我会验证这是安全的以防万一。如果不是,为什么会溢出堆栈?

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 来跟踪完成和异常。

我当然不会推荐将此作为重复工作的模式(部分原因是我提到的内存泄漏),但我希望这能解释为什么您没有遇到堆栈溢出。

关于c# - 我可以在不溢出堆栈的情况下递归调用异步函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25444809/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com