2010-11-05 243 views
4

我想運行一些異步工作流程,然後等待它打印一些結果之前完成,例如:如何等待異步完成

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" 

當我運行這一點,我希望所有的DoWork的調用在打印完成之前完成。但是我得到的結果是這樣的:

工件2 工件3 工作4 工作5 完成 工件1

我試圖除去creatework異步(),但「成品」是異步工作流程之前打印正在運行。

在真正的dowork中,程序執行一些IO操作,所以我想在繼續之前等待最慢的一個完成。

+0

您可以跟蹤完成的數量以及完成打印完成後的數量。不過,可能有更好的方法,我不能拿出它的atm。 – 2010-11-05 14:35:37

+0

跟蹤如何? – yanta 2010-11-05 14:43:30

+0

是不是在等異步完成一個矛盾的排序? – 2010-11-05 15:08:10

回答

7

那麼回答我自己的問題似乎是跛腳,但這似乎工作。有人拿出更好的東西,所以我可以獎勵他們的答案:)

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

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

creatework()  
printfn "finished" 

它提供了不同的輸出,但「已完成」迄今總是在最後...

+2

這是正確的答案。您在異步塊內調用'Async.Start'的原始代碼非常不習慣。 'Async.Parallel'是做fork-join並行的正確方法。 – Brian 2010-11-05 16:15:25

+2

微小的重構:而不是'Seq.map(有趣的x - > dowork x)'你可以做'Seq.map dowork'。 – 2010-11-05 17:55:33

+0

@布萊恩謝謝澄清 @Greg好點 - 更新 – yanta 2010-11-05 18:08:04

1

我發現,它的方便使用MailboxProcessor確保所有副作用(例如printfn)發生在同一個線程上。使用MailboxProcessor.PostAndReply(singleResult)將工作結果(不管是打印的字符串)彙集到同一個同步上下文中,並提供返回聚合值的另一種消息類型。可以使用聯合來表示這些消息的類型。