私は今、MailboxProcessor
で遊んでいます。したがって、私は、コンピュータ上のディレクトリをクロールすることができますいくつかの薬、およびすべてのサブディレクトリを作っ - その後、各ディレクトリ内のファイルを印刷:MailboxProcessor - いつ停止するかを教えてください。
let fileCollector =
MailboxProcessor.Start(fun self ->
let rec loop() =
async { let! file = self.Receive()
printfn "%s" file
return! loop() }
loop())
let folderCollector =
MailboxProcessor.Start(fun self ->
let rec loop() =
async { let! dir = self.Receive()
do! Async.StartChild(
async { let! files = Directory.AsyncGetFiles dir
for z in files do fileCollector.Post z }) |> Async.Ignore
return! loop() }
loop())
let crawler =
MailboxProcessor.Start(fun self ->
let rec loop() =
async { let! dir = self.Receive()
folderCollector.Post dir
do! Async.StartChild(
async { let! dirs = Directory.AsyncGetDirectories dir
for z in dirs do self.Post z }) |> Async.Ignore
return! loop() }
loop())
crawler.Post @"C:\Projects"
printfn "Done" // Message getting fired right away, due to the async stuff.
今folderCollector
、fileCollector
とcrawler
が行われたときに、私は言うだろうか、最後にprintfn
ステートメントが呼び出され、クローラーがすべてのサブディレクトリーを正常にクロールしてすべてのファイルを印刷した後に呼び出されます。 http://tomasp.net/blog/parallel-extra-image-pipeline.aspxにトマスPetricekによって技術showenを使用することにより 、私は次のコード作ることができた:
更新
let folders = new BlockingQueueAgent<string>(100)
let files = new BlockingQueueAgent<string>(100)
let rec folderCollector path =
async { do! folders.AsyncAdd(path)
do! Async.StartChild(
async { let! dirs = Directory.AsyncGetDirectories path
for z in dirs do
do! folderCollector z }) |> Async.Ignore }
let fileCollector =
async { while true do
let! dir = folders.AsyncGet()
do! Async.StartChild(
async { let! fs = Directory.AsyncGetFiles dir
for z in fs do
do! files.AsyncAdd z }) |> Async.Ignore }
let rec printFiles() =
async { let! file = files.AsyncTryGet(75)
match file with
| Some s ->
printfn "%s" s
return! displayFiles()
| None ->() }
let cts = new CancellationTokenSource()
Async.Start(folderCollector @"C:\Projects", cts.Token)
Async.Start(fileCollector, cts.Token)
Async.RunSynchronously(printFiles(), cancellationToken = cts.Token)
printfn "DONE!"
更新:更新:さて、私
let folders = new BlockingQueueAgent<string option>(10)
let files = new BlockingQueueAgent<string option>(10)
let folderCollector path =
async { let rec loop path =
async { do! folders.AsyncAdd(Some path)
let! dirs = Directory.AsyncGetDirectories path
do! [ for z in dirs -> loop z ] |> Async.Parallel |> Async.Ignore }
do! loop path
do! folders.AsyncAdd(None) }
let rec fileCollector() =
async { let! dir = folders.AsyncGet 125
match dir with
| Some s ->
let fs = Directory.GetFiles s
do! [ for z in fs -> printfn "%s" z; files.AsyncAdd(Some z) ] |> Async.Parallel |> Async.Ignore // <-- Fails silence if files are full
do! fileCollector() // <-- unreachable
| None -> printfn "Done!";()}
そのトイレ:コード以下の混ざっ」VEのksええ、ええ?なんらかの理由で、fileCollector()
関数のdo! fileCollector()
行で、files
BlockingQueueAgentがいっぱいの場合、 を実行しないでください。代わりに、それは沈黙に失敗します。私がしなければ
は、しかし:
let folderCollector path =
async { let rec loop path =
async { do! folders.AsyncAdd(Some path)
let! dirs = Directory.AsyncGetDirectories path
do! [ for z in dirs -> loop z ] |> Async.Parallel |> Async.Ignore }
do! loop path
do! folders.AsyncAdd(None) }
let rec fileCollector() =
async { let! dir = folders.AsyncGet 75
match dir with
| Some s ->
let fs = Directory.GetFiles s
do! Async.StartChild(async { do! [ for z in fs -> printfn "%s" z; files.AsyncAdd(Some z) ]
|> Async.Parallel |> Async.Ignore }) |> Async.Ignore
do! fileCollector()
| None -> printfn "Done!";()}
それだけで正常に動作します。しかし、今はfileCollector
が完了した時点を追跡することはできません。なぜなら、それは非同期計算の束を実行しているからです。したがって、キュー内の「なし」になっても、やる必要があるかもしれません。どうしたの?
更新: 私はfolderCollector
と同じ "スタイル" にfileCollector
を変更したが、問題が残っています。修正されたバージョン:
let fileCollector() =
async { let rec loop() =
async { let! dir = folders.AsyncGet 750
match dir with
| Some s ->
let! fs = Directory.AsyncGetFiles s
do! [ for z in fs -> printfn "%A" z; files.AsyncAdd(Some z) ]
|> Async.Parallel |> Async.Ignore
return! loop()
| None -> printfn "Done!";() }
do! loop()
printfn "after" // Never gets this far...
do! files.AsyncAdd(None) }
私の投稿更新を見てください! :)私はそれが私のものかどうかは分かりませんが、 'BlockingQueueAgent'にバグがあります(私はあなたのブログの投稿と同じコードをエージェントのタイプとして使っています)。 – ebb
@ebb - 'fileCollector'を' folderCollector'と同様の方法で修正する必要があると思います(両者が終わりを追うことができるように)。 Aslo、私はfolderCollector' 'と同様の方法で、' filCollector'を変更しようとしました(更新記事を参照) –
(それがより効率的です)、 '!代わりに'やるの再帰呼び出しのために '!'返す使用していますが、問題残っている...私は完全にシンプルなものを見落とさなければならないが、何が見えないのか。 – ebb