多个请求如何从资源管理角度处理Task.Run?

3
我有一些需要“启动并忘记”的代码,意思是调用代码不需要等待响应。如果我在一秒钟内迭代循环并调用此代码10,000次,那么会有10,000个线程飘荡在周围,争夺资源吗?我担心我的计算机会瞬间变得非常缓慢。或者,线程池是否管理这些请求并将它们排队等待解决?换句话说,使用Task.Run()做一些愚蠢的事情有多容易。

只需尝试一下,就会明白线程池的工作原理。 - Hans Passant
你用这一万个线程在做什么?是什么类型的工作? - Yuval Itzchakov
2个回答

3
因此,当您调用Task.Run时,它会创建一个新的 Task 并在TaskScheduler.Default上安排它。这恰好是 ThreadPoolTaskScheduler ,然后将该任务排队到 ThreadPool ThreadPool使用线程池(出奇地)缓慢处理工作项。 ThreadPool在内部管理自己的线程,并在需要时可以创建更多。
对于您的问题:

我会有10,000个浮动的线程,争夺资源吗?

不,ThreadPool通常知道如何有效地管理其线程,并且增长非常缓慢。
但是,您分配许多任务,这些任务会等待完成占用空间。它们还可能保留其他引用(通常是由于捕获),这也占用资源。
顺便说一下,如果您使用不太安全的Task.Factory.StartNew并传递TaskCreationOptions.LongRunning,则创建10,000个后台线程。

那么,你的意思是我基本上可以相信线程池来避免麻烦? - Deane
@Deane 不是真的。我的意思是你不应该因为线程之外的原因而这样做。看看TPL数据流的ActionBlock或其他一些更高级别的结构。 - i3arnon

1
当您调用Task.Run时,您正在将工作排队以在线程池中运行。如果您启动了大量的工作,由于计算资源有限,完成可能需要一段时间。使用Task.Run运行后台任务很容易让自己陷入困境。最好理解情况并使用适合工作的正确工具。如果您想处理大量后台工作,请查看类似TPL、BlockingCollection和Concurrent Collections的内容。像Producer/Consumer流之类的东西是正确的方向,但所有这些都取决于您尝试解决的问题。

在这种情况下,我并不真的关心工作何时完成,只要它实际上完成了。因此,线程池可以等待几分钟,只要最终能够处理它。 - Deane
虽然您可能不在意安排一堆任务,但您可能没有以正确的方式处理事情。如果通过安排所有这些任务,您使用了比所需更多的内存,引入了死锁或存在内存泄漏怎么办?在那些可能并不重要的事情上以正确的方式解决问题,将使您更擅长于以后解决那些真正重要的事情。 - dmarlow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接