在没有 ThreadStarvation 的情况下在 C# 中递归使用任务

Using Tasks recursively in C# without ThreadStarvation

我想弄清楚 C# 中的并发编程(特别是 TaskScheduler、TaskFactory)是否会导致 ThreadStarvation。

我在Java中为分而治之排序算法创建了一个固定线程池,一个任务试图 创建 2 个新的 Childtasks 并等待它们的结果合并它们。当任务等待时,使用的线程需要等待。在某些时候,线程池无法创建更多线程,程序崩溃。你可以通过使用 fork/join-tasks 来解决这个问题,它可以在分叉后跳转到其他工作并等待结果。

在C#中也会出现这种现象吗? 是否还有用于递归算法的 ForkJoinTasks,或者是否不需要它们,因为通常的 Tasks 可以防止这种情况发生? 当任务等待子任务时,我无法找到有关任务行为的信息。

如果您正在使用 async/await,您应该不会出现线程饥饿,因为等待任务不会阻塞任何线程。

如果您在任务中使用 .Wait().Result,线程将阻塞,很可能会发生饥饿。线程池将添加线程以尝试缓解饥饿,但此过程缓慢,因此您的程序可能会挂起。无论如何,使用大量线程只是一个坏主意。

对于排序之类的事情,您可能不希望以递归方式启动任务,因为一旦各个块开始变小,开销就可能开始占主导地位。所以我可能会建议在几次递归之后切换到单线程策略以避免这种情况。或者只是将输入分成 N 个大小相等的桶,其中 N 是可用内核的数量,并行处理这些桶并合并结果。这应该有助于最大限度地减少线程开销。