How to wait for async to finish

2019-02-24 08:27发布

I would like to run some async workflow, then wait for it to finish before printing some results, example:

let dowork n =
    async {
        do printfn "work %d" n
    }

let creatework() =
    async {
        for x in [1..5] do
            Async.Start(dowork x)
    }

Async.RunSynchronously(creatework())    
printfn "finished"

when I run this, I want all the dowork calls to finish before printing "finished". However I get results like this:

work 2 work 3 work 4 work 5 finished work 1

I have tried removing async from creatework() but "finished" is printed before the async workflows are run.

In the real dowork, the program performs some IO, so I want to wait for the slowest one to finish before continuing.

2条回答
等我变得足够好
2楼-- · 2019-02-24 09:22

Well answering my own question seems lame, but this seems to work. Someone come up with something better so I can award them the answer :)

let dowork n =
    async {
        do printfn "work %d" n
    }

let creatework() =
    [1..5] |> Seq.map dowork |> Async.Parallel |> Async.RunSynchronously

creatework()    
printfn "finished"

It gives various output, but "finished" so far is always last...

查看更多
看我几分像从前
3楼-- · 2019-02-24 09:31

I found that it's convenient to use MailboxProcessor to make sure that all side-effects (e.g. printfn) happen on the same thread. Use MailboxProcessor.PostAndReply(singleResult) to funnel work results (be it just the strings to print) into the same synchronization context, and provide for another message type that returns aggregate values. One could use a union for types of these messages.

查看更多
登录 后发表回答