【发布时间】:2020-07-26 04:53:01
【问题描述】:
我有一些线程专用于一项任务(接收和处理请求)和一些线程专用于其他任务(长时间运行/CPU 密集型任务)。 这是一个控制台应用程序。
我想在所有线程中使用 async/await,但我了解到 async/await 使用 managed thread pool 来运行延续,这意味着请求处理可能会因为出现一堆 CPU 密集型任务而延迟(是的,这么多,这就是为什么我有有限的线程数来做这项工作)?
- 如果我想限制并发,那我一定不能使用TAP?
- 如果我想在应用程序的生命周期内做一些后台工作,那么我也不能使用 TAP 吗?
- 我应该用它自己的 SyncronizationContext 编写一个 ThradPool 实现吗?
- 还有其他方法可以在某些线程中运行延续吗?
【问题讨论】:
-
如何通过使用
SetMinThreads方法增加ThreadPool产生的初始线程数?例如ThreadPool.SetMinThreads(100, 10)。 -
@TheodorZoulias 我不喜欢这个解决方案,因为请求处理和长时间运行的任务仍然混合在一个线程池中,这仍然可能导致没有线程来处理请求的情况,因为它们都是忙于长时间运行的任务。而且我真的不需要这么多线程来处理长时间运行的任务(现在 3 个就足够了)。
-
使用
TaskCreationOptions.LongRunning选项启动长时间运行的任务怎么样?顺便说一句,当您说“长时间运行”时,您是指从应用程序开始到结束,还是只持续几秒钟以上? -
LongRunning选项真的没什么特别的。它只是在新线程而不是ThreadPool线程中运行任务。我的猜测是,您长时间运行的任务实际上是被Thread.Sleep延迟的循环。如果是这种情况,那么您可以将Thread.Sleep替换为await Task.Delay,并且具有不需要专用线程的长时间运行的任务。 Here 就是一个例子。 -
在程序的整个生命周期中,这些任务可能不会在紧密循环中旋转。我猜他们大部分时间都在等待什么。他们可以通过使用
SemaphoreSlin.WaitAsync或像Channel这样的异步队列来异步等待,而不是阻塞当前线程。老实说这不会有太大的不同。浪费 3 个线程只是 3 MB 未充分利用的 RAM,这对于现代计算机来说不算什么。
标签: c# multithreading concurrency async-await task