Have you tried using Async.Parallel? That is, instead of Async.Starteach subdirectory, simply combine the tasks of the subdirectory into one asynchronous one using Async.Parallel. Then you get the (nested) fork-join task, which can RunSynchronouslywait for the final result.
EDIT
Here is an approximate code that shows the essence, if not the full detail:
open System.IO
let agent = MailboxProcessor.Start(fun mbox ->
async {
while true do
let! msg = mbox.Receive()
printfn "%s" msg
})
let rec traverse dir =
async {
agent.Post(dir)
let subDirs = Directory.EnumerateDirectories(dir)
return! [for d in subDirs do yield traverse d]
|> Async.Parallel |> Async.Ignore
}
traverse "d:\\" |> Async.RunSynchronously
EDIT 2
Here is a wait version that uses answers:
open System.IO
let agent = MailboxProcessor.Start(fun mbox ->
async {
while true do
let! dir, (replyChannel:AsyncReplyChannel<unit>) = mbox.Receive()
printfn "%s" dir
replyChannel.Reply()
})
let rec traverse dir =
async {
let r = agent.PostAndAsyncReply(fun replyChannel -> dir, replyChannel)
let subDirs = Directory.EnumerateDirectories(dir)
do! [for d in subDirs do yield traverse d]
|> Async.Parallel |> Async.Ignore
do! r
}
traverse "c:\\Projects\\" |> Async.RunSynchronously
Brian source
share