为什么下面的代码在.Net4.8中只进行17层递归就会导致StackOverflowException,但在NetCore 3.1中不会发生这种情况(我可以将计数设置为10,000并且仍然可以正常工作)?
class Program
{
static async Task Main(string[] args)
{
try
{
await TestAsync(17);
}
catch(Exception e)
{
Console.WriteLine("Exception caught: " + e);
}
}
static async Task TestAsync(int count)
{
await Task.Run(() =>
{
if (count <= 0)
throw new Exception("ex");
});
Console.WriteLine(count);
await TestAsync2(count);
}
static async Task TestAsync2(int count) => await TestAsync3(count);
static async Task TestAsync3(int count) => await TestAsync4(count);
static async Task TestAsync4(int count) => await TestAsync5(count);
static async Task TestAsync5(int count) => await TestAsync6(count);
static async Task TestAsync6(int count) => await TestAsync(count - 1);
}
这是.Net 4.8中已知的bug吗?我期望在这样的函数中有超过17层递归... 这是否意味着使用async/await编写递归不被推荐?
更新:简化版本
class Program
{
// needs to be compiled as AnyCpu Prefer 64-bit
static async Task Main(string[] args)
{
try
{
await TestAsync(97); // 96 still works
}
catch(Exception e)
{
Console.WriteLine("Exception caught: " + e);
}
}
static async Task TestAsync(int count)
{
await Task.Run(() =>
{
if (count <= 0)
throw new Exception("ex");
});
Console.WriteLine(count);
await TestAsync(count-1);
}
}
如果选择 任意CPU 且禁用 32位,则只会发生这么快的情况, 但在多台机器上(Windows 1903和1909)的多个.NET版本(.NET 4.7.2和.NET 4.8)中都可以重现此问题。
count < 0
时,它会抛出异常。但在TestAsync6
中,您使用count-1
调用了TestAsync
。无论您从17或2或其他数字开始,迟早都会使用-1
调用它,然后就会出现异常。我认为这是可以预料的。 - Wiktor Zychlacount <= 0
时会抛出异常,如果使用2
调用它,则会抛出异常并且异常将被捕获,一切都很好。但是,当使用17 或更高
的数字调用时,异常将被抛出,但反过来会导致堆栈溢出异常,这是我没有预料到的... - Inspyro