【发布时间】:2019-06-08 00:14:54
【问题描述】:
我有一个MailBoxProcessor,它执行以下操作:
主循环(
type AsyncRunner:https://github.com/kkkmail/ClmFSharp/blob/master/Clm/ContGen/AsyncRun.fs#L257 - 行号可能会随着我不断更新代码而改变)。它生成一些“模型”,将它们中的每一个编译到特定于模型的文件夹中,将它们作为外部进程生成,然后每个模型使用 WCF 通过调用updateProgress“通知”AsyncRunner其进度。一个模型可能需要几天时间才能运行。一旦任何模型完成,跑步者就会生成/产生更多。它设计以 100% 的处理器负载运行(但优先级:ProcessPriorityClass.BelowNormal),但我可以指定要使用的较少数量的逻辑内核(1 到Environment.ProcessorCount之间的某个数字)。目前,我使用… |> Async.Start“异步”编辑了几乎所有进入MailBoxProcessor的内容,以确保我“永远不会”阻塞主循环。我可以通过调用
member this.getState () = messageLoop.PostAndReply GetState来“询问”跑步者(使用 WCF)它的状态。或者我可以向它发送一些命令(再次使用 WCF),例如
member this.start(),member this.stop(),……
这就是有趣的地方。一切正常!但是,如果我运行一个“监视器”,它会通过在无限循环中有效地调用PostAndReply(暴露为this.getState ())来请求一个状态,过一会儿它就会挂断。我的意思是它确实最终会返回,但会有一些无法预测的大延迟(比如几分钟)。同时,我可以发出命令并且它们确实快速返回,而getState 仍然没有返回。
是否有可能使其在接近 100% 的负载下响应?非常感谢!
【问题讨论】:
-
拥有 MailBoxProcessor 和任务时为什么要使用多个进程? MailBoxProcessor 或多或少作为一个单独的进程工作。问题是它相当基础,你必须自己提供 DoP 和背压
-
你应该看看TPL Dataflow。每个处理块在其输入队列中接收消息,并使用您提供的具有可配置并行度的函数来处理它们。如果要同时处理 3 条消息,可以将 DOP 设置为 3。通常为 1,因为预计数据流块将在块管道中工作,每个块在单独的线程中运行。这类似于 shell 命令管道的工作原理
-
还可以通过对块的输入缓冲区设置限制来实现背压。如果目标块已满,源块将暂停处理,直到它们可以推送结果
标签: multithreading f# mailboxprocessor heavy-computation