Я использую агент (MailboxProcessor) для выполнения некоторой обработки с отслеживанием состояния, когда требуется ответ.
- Звонящий отправляет сообщение, используя
MailboxProcessor.PostAndAsyncReply
- В агенте ответ дается с
AsyncReplyChannel.Reply
Однако, покопавшись в исходном коде f#, я обнаружил, что агент не будет обрабатывать следующее сообщение, пока не будет доставлен ответ. В целом это хорошо. Но в моем случае агенту предпочтительнее продолжать обрабатывать сообщения, чем ждать доставки ответа.
Это проблематично сделать что-то подобное, чтобы доставить ответ? (Или есть лучшая альтернатива?)
async { replyChannel.Reply response } |> Async.Start
Я понимаю, что этот метод не гарантирует, что ответы будут доставлены по порядку. Я не против.
Справочный пример
// agent code
let doWork data =
async { ... ; return response }
let rec loop ( inbox : MailboxProcessor<_> ) =
async {
let! msg = inbox.Receive()
match msg with
| None ->
return ()
| Some ( data, replyChannel ) ->
let! response = doWork data
replyChannel.Reply response (* waits for delivery, vs below *)
// async { replyChannel.Reply response } |> Async.Start
return! loop inbox
}
let agent =
MailboxProcessor.Start(loop)
// caller code
async {
let! response =
agent.PostAndAsyncReply(fun replyChannel -> Some (data, replyChannel))
...
}
PostAndAsyncReply
, так зачем вообще это использовать? Попросите клиента передать, скажем, наблюдаемую тему и втолкнуть в нее ваши ответы. - person Fyodor Soikin   schedule 08.02.2017AsyncReplyChannel
внутренне используетManualResetEvent
, чтобы сигнализировать о готовности результата. Поэтому, когда вызываетсяReply
, он не возвращается до тех пор, пока не будет доставлен ответ. Это действие заставляет агента ждать, пока вызывающая сторона не получит ответ, прежде чем обрабатывать следующее сообщение. - person Kasey Speakman   schedule 08.02.2017MailboxProcessor
, знает ответ или лучшую альтернативу. - person Kasey Speakman   schedule 08.02.2017