バックグラウンド。
MailboxProcessor を把握しようとしています。アイデアは、ある種のステート マシンとして使用し、ステート間で引数を渡し、終了することです。一部の部分は非同期通信を行う予定なので、そこで Sleep を作成しました。これはコンソール アプリケーションです。メイン スレッドが終了し、その背後にあるすべてのものを強制終了するため、Post を作成しても何もしません。メインで PostAndReply を作成しています。また、私はなしで試しました
let sleepWorkflow = async
、違いはありません。
質問。
(多分私は何か間違ったことをしている)
Go24 は非同期ではありません。RunSynchronously を StartImmediate に変更しても、目に見える違いはありません。代わりに、末尾は GetMe の下のどこかにあるはずです。同時に、Fetch の後に Done が出力されます。スリープ時に制御がメインスレッドに戻されるはずがありませんか?
Go24、待って go24 1、フェッチを終了 1 完了 GetMe ...
実行時間はひどく遅いです。Fetch の遅延なしで、約 10 秒 (ストップウォッチ) です。F# スレッドは軽量であり、threadpool を使用する必要があると考えました。デバッガーによると、すべてを作成するのに appr 1 秒かかり、実際のスレッドのように見えます。
また、[1..100] に変更すると、100 秒間プログラムが「一時停止」されます。ProcessExplorer によると、その間に 100 のスレッドが作成され、その後すべてが出力されます。私は実際には、より少ないスレッドとゆっくりとした増加を好みます。
コード。
Program.fs
[<EntryPoint>]
let main argv =
let a = Mailbox.MessageBasedCounter.DoGo24 1
let a = Mailbox.MessageBasedCounter.DoFetch 1
let b = Mailbox.MessageBasedCounter.GetMe
let task i = async {
//Mailbox.MessageBasedCounter.DoGo24 1
let a = Mailbox.MessageBasedCounter.DoFetch i
return a
}
let stopWatch = System.Diagnostics.Stopwatch.StartNew()
let x =
[1..10]
|> Seq.map task
|> Async.Parallel
|> Async.RunSynchronously
stopWatch.Stop()
printfn "%f" stopWatch.Elapsed.TotalMilliseconds
printfn "a: %A" a
printfn "b: %A" b
printfn "x: %A" x
0 // return an integer exit code
メールボックス.fs
module Mailbox
#nowarn "40"
type parserMsg =
| Go24 of int
| Done
| Fetch of int * AsyncReplyChannel<string>
| GetMe of AsyncReplyChannel<string>
type MessageBasedCounter () =
/// Create the agent
static let agent = MailboxProcessor.Start(fun inbox ->
// the message processing function
let rec messageLoop() = async{
let! msg = inbox.Receive()
match msg with
| Go24 n ->
let sleepWorkflow = async{
printfn "Go24, wait"
do! Async.Sleep 4000
MessageBasedCounter.DoDone() // POST Done.
printfn "go24 %d, end" n
return! messageLoop()
}
Async.RunSynchronously sleepWorkflow
| Fetch (i, repl) ->
let sync = async{
printfn "Fetch %d" i
do! Async.Sleep 1000
repl.Reply( "Reply Fetch " + i.ToString() ) // Reply to the caller
return! messageLoop()
}
Async.RunSynchronously sync
| GetMe (repl) ->
let sync = async{
printfn "GetMe"
repl.Reply( "GetMe" ) // Reply to the caller
return! messageLoop()
}
Async.RunSynchronously sync
| Done ->
let sync = async{
printfn "Done"
return! messageLoop()
}
Async.RunSynchronously sync
}
// start the loop
messageLoop()
)
// public interface to hide the implementation
static member DoDone () = agent.Post( Done )
static member DoGo24 (i:int) = agent.Post( Go24(i) )
static member DoFetch (i:int) = agent.PostAndReply( fun reply -> Fetch(i, reply) )
static member GetMe = agent.PostAndReply( GetMe )