使用 Post 或 PostAndAsyncReply with F# 的 MailboxProcessor?



我已经看到了不同的片段,演示了Put消息返回unit与f#的MailboxProcessor。在某些情况下,只使用Post方法,而其他情况下使用PostAndAsyncReply,一旦消息被处理,应答通道立即应答。在做一些测试时,我发现等待回复时有明显的时间滞后,所以似乎除非您需要真正的回复,否则您应该使用Post

注意:我开始问这个在另一个线程,但认为它有用的帖子作为一个完整的问题。在另一个线程中,Tomas Petricek提到回复通道可以使用等待机制来确保调用者延迟直到Put消息被处理。

使用PostAndAsyncReply是否有助于消息排序,或者它只是强制暂停,直到第一个消息被处理?就性能而言,Post似乎是正确的解决方案。这准确吗?

更新:

我只是想到了PostAndAsyncReplyBlockingQueueAgent示例中可能是必要的原因:Scan用于在队列满时查找Get消息,因此您不想在前一个Put完成之前先查找Put然后再查找Get

我的建议是在设计系统时尽可能多地使用Post

该技术是为异步并发性设计的,其目标是发送即忘消息。等待响应的想法直接违背了这一点。

我想我基本上同意你的总结——PostAndAsyncReplyPost慢是有道理的,所以如果调用者在操作(比如将值放入队列)完成时不需要从代理那里获得通知,那么它肯定应该公开一种方法,只使用Post来做到这一点。PostAndAsyncReply慢得多的事实可能意味着一些代理应该公开两个选项并让调用方决定。

关于BlockingQueueAgent的具体示例(或我用来实现单位置缓冲区的类似示例),代理的典型应用是解决消费者-生产者问题。在消费者-生产者问题中,我们希望在队列满时阻塞生产者,在队列空时阻塞消费者。. net BlockingCollection只支持同步阻塞,这有点糟糕(即它可以阻塞整个线程池)。

使用PostAndAsyncReply发送Put消息的BlockingQueueAgent,我们可以等待直到元素被异步添加到队列中(所以它阻塞了生产者,但没有阻塞线程!)一个典型用法的例子是我前段时间编写的图像处理管道。下面是其中的一个片段:

// Phase 2: Scale to a thumbnail size and add frame
let scalePipelinedImages = async {
   while true do 
     let! info = loadedImages.AsyncGet()
     scaleImage info
     do! scaledImages.AsyncAdd(info) }

这个循环反复地从loadedImages队列中获取图像,进行一些处理并将结果写入scaledImages。使用队列的阻塞(读取和写入时)控制并行性,因此管道的步骤并行运行,但如果管道不能以所需的速度处理它们,它不会继续加载越来越多的图像。

相关内容

  • 没有找到相关文章

最新更新