gpt4 book ai didi

c# - 递归调用 async-void : any guarantee on the stack limit?

转载 作者:太空宇宙 更新时间:2023-11-03 21:36:36 25 4
gpt4 key购买 nike

面对这个奇怪的案例,我想知道这种模式是否会对堆栈使用产生任何保证(即可靠与否)。

注意:计数器只是“DoIt”函数中要做的一项假设工作。

class Program
{
static void Main(string[] args)
{
DoIt();
Console.ReadKey();
_flag = true;
}


private static bool _flag;
private static int _count;

private static async void DoIt()
{
await Task.Delay(1000);
_count++;
if (_flag) return;
DoIt();
}
}

“DoIt”任务应该永远调用自己,直到某些东西(即标志)破坏递归。我想知道堆栈是否填满,因为它反对“异步”调用,不应该停止调用者。

主要问题是:在某些情况下我可能会遇到 StackOverflow 异常,还是我保证不会发生异常?

如果我也删除延迟会怎么样?

至于我,该模式应该(几乎)始终是安全的,但老实说我不会解释如何保证它(至少在不分析背后的 IL 代码的情况下)。只是怀疑循环何时非常紧密,以至于异步调用变得比整个函数本身“慢”。

最佳答案

不,你最终会在很多任务上安排很多延续,而不是深度堆栈......至少在初始调用中是这样。

请注意,这只是因为您正在使用

await Task.Delay(1000);

... 可以合理地预期永远不会返回已经完成的任务。如果你有类似的东西:

var value = await cache.GetAsync(key);

它可能很容易返回一个已完成的任务,然后你真的可以得到一个非常深的堆栈。

您需要记住的是,调用是同步的,直到它遇到第一个 await未完成 等待。

What if I also remove the delay?

然后您将有效地拥有一个递归调用自身的同步方法,并且除非很快设置标志真的,否则您将以堆栈溢出而告终。

请注意,即使您在当前代码中没有遇到堆栈溢出,您仍然每秒安排一个新任务,直到设置标志,这并不理想 - 它远非糟糕,因为任务无论如何都会很快消失,但如果可能的话我仍然会使用循环。

一个潜在的问题是,我相信“逻辑”堆栈仍然被捕获……并且随着您的进行,它会变得越来越大。不过,这可能只是调试时的情况 - 我不是这方面的专家。

关于c# - 递归调用 async-void : any guarantee on the stack limit?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21461326/

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