我看到了不同的代码段,展示了Put
消息,该消息通过F#的unit
返回MailboxProcessor
。在某些情况下,仅使用Post
方法,而其他方法使用PostAndAsyncReply
,一旦处理完消息,回复通道立即回复。在进行一些测试时,我在等待回复时发现了一个显着的时滞,所以看起来除非你需要真正的回复,否则你应该使用Post
。
注意:我开始在another thread中提出此问题,但认为发布完整问题很有用。在另一个帖子中,Tomas Petricek提到回复频道可以使用等待机制来确保呼叫者延迟直到Put
消息被处理。
使用PostAndAsyncReply
是否有助于消息排序,还是只是强制暂停直到第一条消息被处理?在性能方面Post
出现了正确的解决方案。那是准确的吗?
更新
我刚刚想到了BlockingQueueAgent
example中可能需要PostAndAsyncReply
的原因:Scan
用于在队列已满时查找Get
消息,所以你不要在上一个Put
完成之前,我想要Get
然后Put
。
答案 0 :(得分:4)
我的建议是设计您的系统,以便尽可能使用Post
。
该技术专为异步并发而设计,其目标是发送即发消息。等待回应的想法直接违背了这一点。
答案 1 :(得分:3)
我认为我一般都同意你的摘要 - PostAndAsyncReply
慢于Post
是有意义的,所以如果调用者在操作时不需要从代理获得通知(例如在将值放入队列中)完成后,它应该只使用Post
公开一种方法。 PostAndAsyncReply
慢得多的事实可能意味着某些代理应该公开这两个选项并让调用者决定。
关于BlockingQueueAgent
的具体示例(或我用于实现单位缓冲区的类似示例),代理的典型应用是解决消费者 - 生产者问题。在消费者 - 生产者问题中,我们希望在队列满时阻止生产者,并在消费者为空时阻止消费者。 .NET BlockingCollection
仅支持同步阻塞,这有点不好(即它可以阻塞整个线程池)。
使用使用BlockingQueueAgent
发送Put
消息的PostAndAsyncReply
,我们可以等到元素异步添加到队列中(因此它会阻塞生成器,但不会阻塞线程!)典型用法的一个例子是我前段时间写的image processing pipeline。这是一个片段:
// 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
。使用队列的阻塞(在读取和写入时)都控制并行性,因此管道的步骤并行运行,但如果管道无法以所需的速度处理它们,则不会继续加载越来越多的图像。