使用 Async/Await 的无限递归调用永远不会抛出异常

Nuc*_*mer 2 .net c# recursion task-parallel-library async-await

我正在编写一个小型控制台应用程序,以尝试熟悉使用 async/await。在这个应用程序中,我不小心创建了一个无限递归循环(我现在已经修复了)。不过,这个无限递归循环的行为让我感到惊讶。它没有抛出StackOverflowException,而是陷入僵局。

考虑以下示例。如果Foo()使用runAsyncset to调用false,它会抛出一个StackOverflowException。但是当runAsyncis 时true,它会陷入僵局(或至少看起来会)。谁能解释为什么行为如此不同?

bool runAsync;
void Foo()
{
    Task.WaitAll(Bar(),Bar());
}

async Task Bar()
{
   if (runAsync)
      await Task.Run(Foo).ConfigureAwait(false);
   else
      Foo();
}
Run Code Online (Sandbox Code Playgroud)

usr*_*usr 6

并没有真正陷入僵局。这会很快耗尽线程池中的可用线程。然后,每 500 毫秒注入一个新线程。当您Console.WriteLine在那里放置一些日志时,您可以观察到这一点。

基本上,这段代码是无效的,因为它压倒了线程池。任何有这种精神的东西都不能投入生产。

如果您将所有等待Task.WaitAll变为异步而不是使用,则会将明显的死锁变成失控的内存泄漏。这对你来说可能是一个有趣的实验。