邮箱处理器何时停止运行?

sdg*_*sdh 5 f#

我无法理解MailboxProcessorF# 中的“完成”时间。

我收集了一些行为(可能)违反直觉的例子。

该邮箱处理器不打印任何内容并停止程序:

let m = MailboxProcessor.Start (fun inbox -> async {
  while true do
    let! m = inbox.Receive()
    printfn "%i" m
})
Run Code Online (Sandbox Code Playgroud)

该邮箱处理器计数直到2207程序退出:

MailboxProcessor.Start (fun inbox -> async {
  let mutable i = 0;
  while true do
    printfn "%i" i
    i <- i + 1
})
|> ignore
Run Code Online (Sandbox Code Playgroud)

该邮箱处理器打印1然后程序退出:

let m = MailboxProcessor.Start (fun inbox -> async {
  while true do
    let! m = inbox.Receive()
    printfn "%i" m
    do! Async.FromContinuations ignore // Should wait forever
})

m.Post(1)
m.Post(2)
m.Post(3)
Run Code Online (Sandbox Code Playgroud)

你能解释一下为什么MailboxProcessor会有这样的行为吗?

Tom*_*cek 7

启动时,MailboxProcessor将运行指定为主体的异步计算。它将继续运行,直到主体完成(通过到达末尾或抛出异常)或直到程序本身终止(因为邮箱处理器在后台运行)。

对你的例子发表评论:

  • 该邮箱处理器不打印任何内容并停止程序- 我假设您在控制台应用程序中运行它,该应用程序在创建邮箱处理器后终止。没有任何东西阻止程序,因此它结束(在后台杀死邮箱处理器)。

  • 这个邮箱处理器计数到 2207 然后程序退出- 我怀疑这是出于同样的原因 - 你的程序创建邮箱处理器,它设法运行一段时间,但随后程序本身被终止,邮箱处理器被杀死。

  • 该邮箱处理器打印 1,然后程序退出- 邮箱处理器的主体挂起,接下来的两条消息排队。队列永远不会被处理(因为主体已挂起),然后您的程序终止。

如果您在Console.ReadLine()程序末尾添加类似的内容,您将获得更有用的见解,因为这将防止程序终止并杀死邮箱处理器。

例如,以下将处理所有 100000 个项目:

let mbox = MailboxProcessor.Start (fun inbox -> async {
  while true do 
    let! msg = inbox.Receive()
    printfn "%d" msg
})
for i in 0 .. 100000 do mbox.Post(i)
System.Console.ReadLine()
Run Code Online (Sandbox Code Playgroud)