MailboxProcessor使用指南?

时间:2010-08-09 20:24:40

标签: f# concurrency

我刚刚在F#中发现了MailboxProcessor并且它被用作“状态机”......但我对它们的推荐用法找不到多少。

例如...说我正在制作一个有100个屏幕上敌人的简单游戏,我应该使用MailboxProcessor来改变敌人的位置和健康状况;给我200个活动的MailboxProcessor?

引擎盖下是否有任何聪明的线程管理?我应该尝试限制我拥有的活动邮箱处理器的数量,还是可以不断地敲打它们?

提前致谢,

JD。

4 个答案:

答案 0 :(得分:14)

用于敌人模拟的邮箱处理器可能如下所示:

MailboxProcessor.Start(fun inbox ->
async {
  while true do
    let! message = inbox.Receive()
    processMessage(message)
})

在等待消息到达时(let! message =行),它不消耗线程。但是,一旦消息到达,它将消耗一个线程(在线程池上)。如果您有100个邮箱处理器同时收到一条消息,它们都将尝试唤醒并使用一个线程。由于此处消息处理受CPU限制,因此100个邮箱处理器将全部唤醒并开始生成(线程池)线程。这不是一个很好的表现。

邮箱处理器擅长的一种情况是,有许多并发客户端都向一个处理器发送消息(想象几个并行网络爬虫都下载页面并将结果下沉到队列中)。屏幕上的敌人案例看起来不同 - 它是许多实体响应单个消息来源(玩家移动/时间刻度)。

成千上万的邮箱处理器是一个很好的解决方案的另一个例子是I / O绑定的MailboxProcessor:

MailboxProcessor.Start(fun inbox ->
async {
  while true do
    let! message = inbox.Receive()
    match message with
    |  ->
         do! AsyncWrite("something")
         let! response = AsyncResponse()
         ...
})

此处在收到消息后,代理会很快产生一个线程但仍需要跨异步操作维护状态。这在实践中可以非常好地扩展 - 您可以运行成千上万的这样的代理:这是编写Web服务器的好方法。

答案 1 :(得分:7)

根据

http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx

你可以毫不犹豫地把它们撞出来。试试吧!他们使用ThreadPool。我没有尝试过这个实时的GUI游戏应用程序,但如果这个“足够好”我也不会感到惊讶。

答案 2 :(得分:6)

  如果我使用邮箱处理器来改变敌人的位置和健康状况,我说我正在制作一个有100个屏幕上敌人的简单游戏;给我200个活动的MailboxProcessor?

我认为没有理由尝试使用MailboxProcessor。串行循环可能更简单,更快。

  

引擎盖下是否有任何聪明的线程管理?

是的,很多。但它是否设计用于异步并发编程(特别是可扩展的IO),而您的程序实际上并没有这样做。

  

我应该尝试限制我拥有的活动邮箱处理器的数量,还是可以不断地敲打它们?

你可以毫不犹豫地敲打他们,但他们远没有优化,性能比串行代码差很多。

答案 3 :(得分:5)

也许thisthis可以提供帮助吗?