[英]Wait on the mailboxprocessor
是否可以等待郵箱處理器,以下代碼在F#交互中有效,但是有沒有辦法在應用程序或單元測試中等待它?
[<TestMethod>]
member this.TestMailboxProcessor() =
let mailboxProcessor = MailboxProcessor<string>.Start(fun inbox ->
async {
while true do
let! msg = inbox.Receive()
printfn "agent got message %s" msg // too late, UnitTest exits
}
)
mailboxProcessor.Post "ping"
Console.WriteLine "message posted" // I see this in the console
Assert.IsTrue(true)
在這種情況下,這是不可能的,但是您可以定義消息類型以包括AsyncReplyChannel <'t> ,然后允許您使用MailboxProcessor.PostAndReply而不是Post。 這樣,調用代碼可以(同步或異步)等待響應值,或者至少等待處理已完成的指示。
您修改后的源代碼可能如下所示:
[<TestMethod>]
member this.TestMailboxProcessor() =
let mailboxProcessor =
MailboxProcessor<string * AsyncReplyChannel<unit>>.Start(fun inbox ->
async {
while true do
let! msg, replyChannel = inbox.Receive()
printfn "agent got message %s" msg
(*
Reply takes a value of the generic param of
AsyncReplyChannel<'t>, in this case just a unit
*)
replyChannel.Reply()
}
)
(*
You can't create an AsyncReplyChannel<'t> value, but this does it for you.
Also always, always use timeouts when awaiting message replies.
*)
mailboxProcessor.PostAndReply(
(fun replyChannel -> "ping", replyChannel),
timeout = 1000)
(* This gets printed only after the message has been posted and processed *)
Console.WriteLine "message posted"
Assert.IsTrue(true)
但是,MailboxProcessor的主題有點棘手,因此請確保始終使用超時,否則,如果代碼中出現錯誤或導致消息循環中斷的異常,則代碼將永遠掛起。 測試不佳,甚至生產不佳。
您應該使用PostAndAsyncReply
或PostAndReply
(阻止版本)
let replyAgent = MailboxProcessor.Start(fun inbox ->
let rec loop() =
async {
let! (replyChannel: AsyncReplyChannel<_>), msg = inbox.Receive()
replyChannel.Reply (sprintf "replied for message: %A" msg)
return! loop()
}
loop() )
let reply = replyAgent.PostAndReply(fun replCh -> replCh, "Hi")
printfn "%s" reply //prints "replied for message: Hi"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.