【发布时间】:2018-10-12 15:11:55
【问题描述】:
我是 F# 的新手,正在尝试使用 MailboxProcessor 来确保状态更改是独立完成的。
简而言之,我将操作(描述状态更改的不可变对象)发布到 MailboxProcessor,在递归函数中我读取消息并生成新状态(即在下面的示例中将项目添加到集合中)并将其发送状态到下一次递归。
open System
type AppliationState =
{
Store : string list
}
static member Default =
{
Store = List.empty
}
member this.HandleAction (action:obj) =
match action with
| :? string as a -> { this with Store = a :: this.Store }
| _ -> this
type Agent<'T> = MailboxProcessor<'T>
[<AbstractClass; Sealed>]
type AppHolder private () =
static member private Processor = Agent.Start(fun inbox ->
let rec loop (s : AppliationState) =
async {
let! action = inbox.Receive()
let s' = s.HandleAction action
Console.WriteLine("{s: " + s.Store.Length.ToString() + " s': " + s'.Store.Length.ToString())
return! loop s'
}
loop AppliationState.Default)
static member HandleAction (action:obj) =
AppHolder.Processor.Post action
[<EntryPoint>]
let main argv =
AppHolder.HandleAction "a"
AppHolder.HandleAction "b"
AppHolder.HandleAction "c"
AppHolder.HandleAction "d"
Console.ReadLine()
0 // return an integer exit code
预期输出是:
s: 0 s': 1
s: 1 s': 2
s: 2 s': 3
s: 3 s': 4
我得到的是:
s: 0 s': 1
s: 0 s': 1
s: 0 s': 1
s: 0 s': 1
阅读 MailboxProcessor 的文档并在谷歌上搜索,我的结论是它是一个消息队列,由“单线程”处理,但看起来它们都是并行处理的。
我完全不在场了吗?
【问题讨论】:
-
我根据我的怀疑发布了一个答案,但是如果您可以发布一个重现该问题的最小完整示例(例如,包括
ApplicationState和HandleAction的 shell 版本),它将有助于确定问题的根本原因。 -
更改了代码以包含问题的完全可执行外壳,认为它与启动多个代理有关,然后与现在与单个代理有关。 @亚伦
-
我已经根据你的新代码示例更新了我的答案
标签: multithreading f# agent mailboxprocessor