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

标签 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

最佳答案

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

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!)异步执行嵌套工作流,然后继续执行当前工作流从那时起。也就是说,do!“之下”的所有内容都被放入一个延续中,一旦 do!“之后”的事物完成,该延续就会被调用。

Async.Start 在(另一个)后台线程上启动工作流并立即返回,而无需等待它完成。

关于f# - 如何将下载程序转换为异步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38403635/

相关文章:

f# - JsonProvider "This is not a constant expression or valid custom attribute value"

f# - 如何更快地读取数据?

c# - 如何将 F# 类型提供程序生成的类型公开给 C# 和 XAML

f# - 使用 F# 进行优化

f# - 如何将浮点值写入 f# 中的文件

f# - async { ... AsyncAdd ... } 和 async { ... do AsyncAdd ... } 有什么区别?

f# - fsharp 通过方括号引用来赋值

f# - 检查传入请求是否包含特定 header 值的最简单方法是什么

F#.Data HTML 解析器从节点提取字符串

f# - FSharp.Data Csv.Load() 失败,仅支持 Web 位置