【问题标题】:F# / MailBoxProcessor is unresponsive to PostAndReply under nearly 100% loadF# / MailBoxProcessor 在接近 100% 的负载下对 PostAndReply 没有响应
【发布时间】:2019-06-08 00:14:54
【问题描述】:

我有一个MailBoxProcessor,它执行以下操作:

  1. 主循环(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 的内容,以确保我“永远不会”阻塞主循环。

  2. 我可以通过调用 member this.getState () = messageLoop.PostAndReply GetState 来“询问”跑步者(使用 WCF)它的状态。

  3. 或者我可以向它发送一些命令(再次使用 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


【解决方案1】:

我建议不要在你的主程序中异步任何东西(除了你产生的进程),因为你的代码会创建额外的进程。在处理 GetState() 方法之前,您的主循环正在等待循环返回以继续。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多