如何使用MailboxProcessor创建作业队列?

时间:2009-06-24 21:52:06

标签: f#

我正在尝试使用MailboxProcessor建模异步作业处理框架。我的要求是启动,停止,暂停和恢复作业处理器。我可以使用MailboxProcessor构建暂停/恢复功能吗?我也应该能够停下来开始吗?我试图在Windows服务后建模。

我在C#中使用Queue / Threads实现了一个系统。我正在寻找设计替代品,就在我看到MailboxProcessor的时候。我相信我可以使用它,但无法弄清楚如何处理上述情况。那么有可能实现这个功能吗?

2 个答案:

答案 0 :(得分:9)

当然:)只需保留一个内部作业队列,并在作业处理器处于启动模式时通过队列进行枚举。在任何其他模式下,只需将新作业排入队列,直到处理器进入启动模式。

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停止,它就无法重新启动,并且所有排队的作业都不会运行(它很容易改变这种行为,因此,它不会杀死队列,而只是不会将作业排入Stop状态)。

如果您需要邮箱处理器和代码之间的双向通信,请使用MailboxProcessor.PostAndReply

答案 1 :(得分:3)

您可能需要查看Luca's blog,因为我认为它有some recent relevant stuff