2010-11-05 176 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)将工作结果(不管是打印的字符串)汇集到同一个同步上下文中,并提供返回聚合值的另一种消息类型。可以使用联合来表示这些消息的类型。