当然:)只要持有的作业的内部队列中,并通过枚举队列作业时,处理器处于启动模式。在任何其他模式下,只需排队新作业,直到处理器进入启动模式。
type 'a msg = // '
| Start
| Stop
| Pause
| Job of (unit -> unit)
type processQueue() =
let mb = MailboxProcessor.Start(fun inbox ->
let rec loop state (jobs : System.Collections.Generic.Queue<_>) =
async {
if state = Start then
while jobs.Count > 0 do
let f = jobs.Dequeue()
f()
let! msg = inbox.Receive()
match msg with
| Start -> return! loop Start jobs
| Pause -> return! loop Pause jobs
| Job(f) -> jobs.Enqueue(f); return! loop state jobs
| Stop -> return()
}
loop Start (new System.Collections.Generic.Queue<_>()))
member this.Resume() = mb.Post(Start)
member this.Stop() = mb.Post(Stop)
member this.Pause() = mb.Post(Pause)
member this.QueueJob(f) = mb.Post(Job f)
此类行为与预期:您可以排队工作在暂停状态,但他们只会在启动状态下运行。一旦processQueue被停止,它就不能被重新启动,并且没有一个入队的作业会运行(它很容易改变这种行为,这样就不会杀死队列,而是不会使作业进入停止状态)。
使用MailboxProcessor.PostAndReply,如果你需要的邮箱处理器和代码之间的双向通信。
+1稍微改进:可以通过使状态变为明确来使代码更加清晰。然后你也可以把所有的状态封装在`state`类型中,特别是只有`Paused`状态会有一个队列。另外,您可能希望将这些状态表示为相互递归的异步工作流程...... – 2011-04-23 23:11:06