Я пытался научиться использовать асинхронные методы на основе сообщений. Ниже приведен упрощенный вариант того, что я пытался сделать. Я пытаюсь использовать конечный автомат в пределах MailboxProcessor
внутри объекта. В целом кажется, что логика может быть гораздо более простой по сравнению с использованием методов, основанных на событиях. У меня проблема, но когда я пытаюсь использовать Async.Parallel
. В коде, следующем за оператором printfn "Eval %i" v
, производится оценка дважды для i1
& i2
вместо одного раза для каждого. Это заставляет меня думать, что я неправильно использую Async.Parallel
. Существует ли альтернативный метод, который должен использоваться в асинхронном рабочем процессе?Как использовать Async.Parallel в асинхронном рабочем процессе?
type Input(v) =
let agent =
MailboxProcessor.Start(fun inbox ->
let rec loop() =
async {
let! (msg : AsyncReplyChannel<int>) = inbox.Receive()
printfn "Eval %i" v
msg.Reply(v)
return! loop()
}
loop())
member this.Eval = agent.PostAndAsyncReply(fun r -> r)
let i1 = Input(1)
let i2 = Input(2)
async {
let! nodeValues = [ i1; i2 ]
|> Seq.map(fun n -> n.Eval)
|> Async.Parallel
return nodeValues
}
|> Async.RunSynchronously
Вам не нужен блок 'async {}'. '[i1; i2] |> Seq.map (fun n -> n.Eval) |> Async.Parallel |> Async.RunSynchronously' будет работать. – Daniel
Спасибо за комментарий, но фактическая реализация не выполняется синхронно. Мой вопрос заключается в том, как параллельно вычислять массив async-возвратов (в этом случае метод Eval) параллельно в async-потоке. См. [Link] (https://gist.github.com/mndrake/8440854#file-utopia-fsx-L121) для более крупного примера. – mndrake
Возможно, просто передайте результат 'Async.Parallel' в' Async.Ignore>> Async.Start'? Что вы хотите делать с результатами «Eval» после их завершения? – Tarmil