Я думаю, что я в целом согласен с вашим резюме - имеет смысл, что PostAndAsyncReply
медленнее, чем Post
, поэтому если вызывающей стороне не нужно получать уведомление от агента при выполнении операции (например, при вводе значения в очередь), это определенно должно предоставить способ сделать это, используя Post
. Тот факт, что PostAndAsyncReply
намного медленнее, вероятно, означает, что некоторые агенты должны предоставить оба варианта и позволить вызывающему абоненту решить.
Что касается конкретного примера BlockingQueueAgent
(или аналогичного примера, который я использовал для реализации одноразового буфера), типичным применением агента является решение проблемы потребитель-производитель. В проблеме «потребитель-производитель» мы хотим заблокировать производителя, когда очередь заполнена, и заблокировать потребителя, когда она пуста. .NET BlockingCollection
поддерживает только синхронную блокировку, что немного плохо (то есть может блокировать весь пул потоков).
Используя BlockingQueueAgent
, который отправляет сообщение Put
, используя PostAndAsyncReply
, мы можем ожидать асинхронного добавления элемента в очередь (поэтому он блокирует производителя, но без блокировки потоков!) Пример типичного используется конвейер обработки изображений , который я написал некоторое время назад. Вот один фрагмент из этого:
// 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
. Блокировка с использованием очереди (как при чтении, так и при записи) контролирует параллелизм, поэтому шаги конвейера выполняются параллельно, но при этом не загружается все больше и больше изображений, если конвейер не может обрабатывать их с требуемой скоростью.