简体   繁体   English

使用Post或PostAndAsyncReply与F#的MailboxProcessor?

[英]Use Post or PostAndAsyncReply with F#'s MailboxProcessor?

I've seen different snippets demonstrating a Put message that returns unit with F#'s MailboxProcessor . 我已经看到了不同的片段展示了一个Put返回消息unit与F#的MailboxProcessor In some, only the Post method is used while others use PostAndAsyncReply , with the reply channel immediately replying once the message is being processed. 在某些情况下,只使用Post方法,而其他人使用PostAndAsyncReply ,一旦处理消息,回复通道立即回复。 In doing some testing, I found a significant time lag when awaiting the reply, so it seems that unless you need a real reply, you should use Post . 在做一些测试时,我发现在等待回复时有很长的时间滞后,所以看起来除非你需要真正的回复,否则你应该使用Post

Note: I started asking this in another thread but thought it useful to post as a full question. 注意:我开始在另一个帖子中询问这个问题,但认为发布完整问题很有用。 In the other thread, Tomas Petricek mentioned that the reply channel could be used a wait mechanism to ensure the caller delayed until the Put message was processed. 在另一个帖子中,Tomas Petricek提到回复通道可以使用等待机制来确保调用者延迟直到Put消息被处理。

Does using PostAndAsyncReply help with message ordering, or is it just to force a pause until the first message is processed? 使用PostAndAsyncReply是否有助于消息排序,还是只是强制暂停直到处理第一条消息? In terms of performance Post appears the right solution. 在性能方面, Post出现了正确的解决方案。 Is that accurate? 那是准确的吗?

Update: 更新:

I just thought of a reason why PostAndAsyncReply might be necessary in the BlockingQueueAgent example : Scan is used to find Get messages when the queue is full, so you don't want to Put and then Get before the previous Put has completed. 我刚刚想到了为什么在BlockingQueueAgent示例中可能需要PostAndAsyncReply的原因:当队列已满时, Scan用于查找Get消息,因此您不希望在前一个Put完成之前先Put然后Get

My advice is to design your system so you can use Post as much as possible. 我的建议是设计你的系统,这样你就可以尽可能地使用Post

This technology was designed for asynchronous concurrency where the objective is to fire-and-forget messages. 该技术专为异步并发而设计,其目标是发送即发消息。 The idea of waiting for a response goes directly against the grain of this. 等待回应的想法直接违背了这一点。

I think I generally agree with your summary - it makes sense that PostAndAsyncReply is slower than Post , so if the caller doesn't need to get a notification from the agent when the operation (such as putting value into the queue) completes, it should definitely expose a way to do that using just Post . 我认为我通常同意你的摘要 - PostAndAsyncReplyPost慢,所以如果调用者在操作(例如将值放入队列)完成时不需要从代理获得通知,那么它应该是肯定会使用Post一种方法。 The fact that PostAndAsyncReply is a lot slower probably means that some agents should expose both options and let the caller decide. PostAndAsyncReply慢得多的事实可能意味着某些代理应公开这两个选项并让调用者决定。

Regarding the specific example of BlockingQueueAgent (or a similar one that I used to implement one-place buffer), the typical application of the agent is to solve the consumer-producer problem. 关于BlockingQueueAgent (或者我用来实现单位缓冲区的类似例子)的具体示例,代理的典型应用是解决消费者 - 生产者问题。 In consumer-producer problem, we want to block the producer when the queue is full and block the consumer when it is empty. 在消费者 - 生产者问题中,我们希望在队列满时阻止生产者,并在消费者为空时阻止消费者。 The .NET BlockingCollection supports only synchronous blocking, which is a bit bad (ie it can block the whole thread pool). .NET BlockingCollection仅支持同步阻塞,这有点不好(即它可以阻塞整个线程池)。

The using the BlockingQueueAgent that sends the Put messsage using PostAndAsyncReply , we can wait until the element is added to the queue asynchronously (so it blocks the producer, but without blocking threads!) An example of typical usage is the image processing pipeline that I wrote some time ago. 在使用BlockingQueueAgent发送该Put使用讯息话题PostAndAsyncReply ,我们可以等到元素被添加到队列异步(所以它会阻止生产国,但不阻塞线程!)典型应用的一个例子是图像处理流水线 ,我写的前一段时间。 Here is one snippet from that: 这是一个片段:

// 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) }

This loop repeatedly gets an image from the loadedImages queue, does some processing and writes the result to scaledImages . 此循环重复从loadedImages队列中获取图像,执行一些处理并将结果写入scaledImages The blocking using the queue (both when reading and when writing) controls the parallelism, so that the steps of pipeline run in parallel, but it does not keep loading more and more images if the pipeline cannot handle them at the required speed. 使用队列的阻塞(在读取和写入时)都控制并行性,因此管道的步骤并行运行,但如果管道无法以所需的速度处理它们,则不会继续加载越来越多的图像。

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

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