[英]Unable to keep state with mailbox processor (F#)
I am attempting to create a list of strings which gets elements gradually inserted into asynchronously with the help of a mailbox processor. 我正在尝试创建一个字符串列表,该列表将在邮箱处理器的帮助下逐步将元素逐步异步插入。 However I am not getting the desired output.
但是我没有得到想要的输出。
I have pretty much followed the code from https://fsharpforfunandprofit.com/posts/concurrency-actor-model/ however it does not seem to work as intended in my case. 我几乎遵循了https://fsharpforfunandprofit.com/posts/concurrency-actor-model/中的代码,但是对于我来说,它似乎无法正常工作。 The code I have is as follows:
我的代码如下:
type TransactionQueue ={
queue : string list
} with
static member UpdateState (msg : string) (tq : TransactionQueue) =
{tq with queue = (msg :: tq.queue)}
static member Agent = MailboxProcessor.Start(fun inbox ->
let rec msgLoop (t : TransactionQueue) =
async{
let! msg = inbox.Receive()
let newT = TransactionQueue.UpdateState msg t
printfn "%A" newT
return! msgLoop newT
}
msgLoop {queue = []}
)
static member Add i = TransactionQueue.Agent.Post i
[<EntryPoint>]
let main argv =
// test in isolation
printfn "welcome to test"
let rec loop () =
let str = Console.ReadLine()
TransactionQueue.Add str
loop ()
loop ()
0
The result i keep getting is a list of the latest input only, the state is not kept. 我一直得到的结果只是最新输入的列表,不保留状态。 So if I enter "a" then "b" then "c" the queue will only have the value "c" instead of "a";"b";"c"
因此,如果我输入“ a”,然后输入“ b”,然后输入“ c”,则队列将仅具有值“ c”,而不是“ a”;“ b”;“ c”
Any help or pointers would be most appreciated! 任何帮助或指针将不胜感激!
Just like C# Properties , your Agent
is really a Property and thus behaves like a method with void
parameter. 就像C#属性一样 ,您的
Agent
实际上是一个属性,因此其行为类似于带有void
参数的方法。 That's why you will get a new agent everytime Agent
property is accessed. 这就是为什么每次访问“
Agent
属性时都会获得一个新代理的原因。
In idiomatic F# there are two styles when implementing agents. 在惯用的F#中,实现代理时有两种样式。 If you don't need to have many agent instances, just write a module and encapsule the agent-related stuff inside.
如果不需要很多代理实例,只需编写一个模块,然后将与代理相关的内容封装在其中。 Otherwise, OOP style should be used.
否则,应使用OOP样式。
Code for style #1 样式#1的代码
module TransactionQueue =
type private Queue = Queue of string list
let private empty = Queue []
let private update item (Queue items) = Queue (item :: items)
let private agent = MailboxProcessor.Start <| fun inbox ->
let rec msgLoop queue = async {
let! msg = inbox.Receive ()
return! queue |> update msg |> msgLoop
}
msgLoop empty
let add item = agent.Post item
[<EntryPoint>]
let main argv =
// test in isolation
printfn "welcome to test"
let rec loop () =
let str = Console.ReadLine()
TransactionQueue.add str
loop ()
loop ()
Code for style #2 样式#2的代码
type Queue = Queue of string list with
static member Empty = Queue []
static member Update item (Queue items) =
Queue (item :: items)
type Agent () =
let agent = MailboxProcessor.Start <| fun inbox ->
let rec msgLoop queue = async {
let! msg = inbox.Receive ()
return! queue |> Queue.Update msg |> msgLoop
}
msgLoop Queue.Empty
member this.Add item = agent.Post item
[<EntryPoint>]
let main argv =
// test in isolation
printfn "welcome to test"
let agent = new Agent ()
let rec loop () =
let str = Console.ReadLine()
agent.Add str
loop ()
loop ()
Notice the use of Single-case union types for the Queue
type. 请注意,对于
Queue
类型,使用了单案例联合类型 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.