確かに:)ジョブの内部キューを保持し、ジョブプロセッサがスタートモードになっているときにキューを列挙するだけです。他のモードでは、プロセッサがスタートモードになるまで新しいジョブをエンキューしてください。
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メールボックスプロセッサとコード間の双方向通信が必要な場合は、MailboxProcessor.PostAndReplyを使用してください。
+1微妙な改善:状態を明示的にすることでコードをより明確にすることができます。次に、すべての状態を 'state'型でカプセル化することができます。特に、' Paused'状態だけがキューを持ちます。また、状態を相互に再帰的な非同期ワークフローとして表現することもできます。 –