在邮箱处理器循环中,我从以前存储在此类集合中的阻塞集合项目中读取。由于我使用相同的循环来写入此类集合,因此我需要将其作为线程启动。
async { process(queue.Take()) } |> Aysync.Start
我的整个代码的执行速度很慢(相对而言(,我怀疑原因是我启动的新线程,尽管我启动了线程池
let toto = ThreadPool.SetMinThreads(300,300)
争用点可能在这里的另一个提示是,如果我只在队列为空时启动(并锁定整个部分((,我的运行时间变化很大,从 350 毫秒到 7 秒,而如果没有,它会保持在 5-10 秒左右。
我的问题是:
- 无论如何我可以在这里加速线程的创建
- 是否有一些结构已经处理了这种情况(消费者/生产者?(可以在邮箱处理器中使用?
如果您需要创建数百个线程来运行 I/O 绑定计算,则可能存在问题。如果计算是 I/O 绑定的,那么应该可以使用相对较少的线程运行它 - 如果它是完全异步的,这意味着线程在任何等待期间都不会被阻塞。
因此,我认为在您的程序中首先要寻找的是线程被阻塞的位置,并将其替换为异步等待。
代码示例中的一个可疑内容是队列,当您调用Take
时,队列可能会阻塞,至少,这就是 .NET 中BlockingCollection
的行为方式。可以尝试将其替换为 BlockingQueueAgent
,后者使用 F# 代理实现相同的功能,但提供异步AsyncTake
方法,可以在不阻塞线程的情况下调用该方法。