如何将下载程序转换为异步?

时间:2016-07-15 19:18:18

标签: f# f#-data

我有以下代码

open FSharp.Data

let downloadFile link =
    ......
    use os = File.Create(...)
    Http.RequestStream(....).ReponseStream.CopyTo(os)

let rec consume() = async {
    ......
    |> Seq.iter (fun x ->
        xxx |> Seq.iter(fun link ->
            downloadFile link
    ))
}

我发现同步下载会导致代码无法同时运行。所以我试着像下面这样做。如何更改它以使用FSharp.Data http AsyncRequestStream?也许CopyTo也可以异步?

open FSharp.Data

let downloadFile link = async {
    ......
    use os = File.Create(...)
    Http.AsyncRequestStream(....).ReponseStream.CopyTo(os) // Error
}

let rec consume() = async {
    ......
    |> Seq.iter (fun x -> 
        xxx |> Seq.iter(fun link ->
            downloadFile link |> Async.Start // do! downloadFile link????
   ))
}
consume() |> Async.RunSynchronously

1 个答案:

答案 0 :(得分:2)

这是一个骨架解决方案,值得您示例中的所有空白点:

let downloadFile link = 
    async {
        ......
        use os = File.Create(...)
        let! resp = Http.AsyncRequestStream(....)
        return resp.ReponseStream.CopyTo(os)
    }

let consume link = 
    async {
        let comps : Async<unit> [] = 
            xxx 
            |> Seq.map (fun link -> downloadFile link)
            |> Array.ofSeq
        return! Async.Parallel comps                
    }

我认为您应该阅读asynchronicity and concurrency in general以及how to use it in F# in particular。从OP来看,整个事情对你来说有点模糊。

修改:回答评论中的问题:

使用return!(或let!do!)异步执行嵌套工作流,然后从该点开始执行当前工作流。也就是说,一切都在&#34;下面&#34; do!被置于一个延续状态,一旦事物发生,就会在#34;之后被调用。 do!结束。

Async.Start激活(另一个)后台线程上的工作流并立即返回而不等待它完成。