繁体   English   中英

邮箱处理器,最新消息

[英]Mailboxprocessor, latest message

设置类似于 一个代理( dataSource )正在生成数据,而单个代理( dataProcessor )正在处理数据。 生成的数据比dataProcessor可以处理的要dataProcessor ,我对处理所有消息不感兴趣,只是处理最新的数据。

Jon Harrop在那里提出的一个可能的解决方案是“当一个人到达时贪婪地吃收件箱中的所有信息并丢弃除了最近的所有信息”。 另一种方法是不监听所有消息,而是dataProcessorPostAndReply dataSource以获取最新的数据。

这些方法的优点和缺点是什么?

这是一个有趣的问题,很可能有几个可能的观点。 我认为最值得注意的方面是选择将影响您在两个组件之间的接口上设计API的方式:

  1. 在“Consume all”方法中,生产者有一个非常简单的API,每当产生一个值并且你的消费者会订阅它时它会触发一些事件。 这意味着您可以让其他订阅者从生产者那里收听更新,并从此问题中做出除消费者之外的其他操作。

  2. 在“Call to get latest”方法中,可能需要编写生成器以使其保持当前状态并丢弃旧值。 然后它将提供阻止异步API以获取最新值。 它仍然可以为其他消费者揭露一个事件。 消费者需要主动轮询更改(在某些类型的繁忙循环中)。

  3. 您也可以在“Consume all”中拥有一个带有事件的生产者,但随后创建另一个侦听任何给定事件的组件,保留最新值并通过阻止异步调用使其可用于任何其他客户端。

这里有一些我能想到的优点/缺点:

  • 在(1)中,制作人非常简单; 消费者更难写
  • 在(2)中,生产者需要做更多的工作,但消费者很简单
  • 在(3)中,您正在添加另一个层,但是以相当可重用的方式。

我可能会选择(2)(如果我只需要一个数据源)或者(3)检查它不会影响性能。

至于(3),我想的是这样的草图:

type KeepLastMessage<'T> = 
  | Update of 'T
  | Get of AsyncReplyChannel<'T>

type KeepLast<'T>(initial:'T, event:IObservable<'T>) = 
  let agent = MailboxProcessor.Start(fun inbox -> 
    let rec loop last = async {
      let! msg = inbox.Receive()
      match msg with 
      | Update last -> return! loop last
      | Get ch -> ch.Reply(last); return! loop last }
    loop initial)
  member x.AsyncGet() = agent.PostAndAsyncReply(Get)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM