gpt4 book ai didi

f# - 使用 fsharp.data.dll 和异步工作流停止 http 下载到磁盘

转载 作者:行者123 更新时间:2023-12-01 05:14:30 25 4
gpt4 key购买 nike

以下 .fsx 文件应该使用 Fsharp.Data.dll 下载并保存到磁盘二进制表基础文件,这些文件作为链接发布在 Internet 上的 html 页面中。

发生的事情是,整个事情在完成一段时间后停滞不前,甚至没有抛出异常或类似的东西。

我很确定,我在异步工作流程中对 CopyToAsync() 的处理有点不当。因为这应该在我小睡时运行,所以如果有人能告诉我应该如何正确完成它会很好。 (更笼统地说——如何在异步工作流中处理 System.Threading.Task 之类的事情?)

#r @"E:\R\playground\DataTypeProviderStuff\packages\FSharp.Data.2.2.3\lib\net40\FSharp.Data.dll"

open FSharp.Data
open Microsoft.FSharp.Control.CommonExtensions
let document = HtmlDocument.Load("http://www.olympuschess.com/egtb/gaviota/")
let links =
document.Descendants ["a"] |> Seq.choose (fun x -> x.TryGetAttribute("href") |> Option.map (fun a -> a.Value()))
|> Seq.filter (fun v -> v.EndsWith(".cp4"))
|> List.ofSeq

let targetFolder = @"E:\temp\tablebases\"
let downloadUrls =
links |> List.map (fun name -> "http://www.olympuschess.com/egtb/gaviota/" + name, targetFolder + name )

let awaitTask = Async.AwaitIAsyncResult >> Async.Ignore

let fetchAndSave (s,t) =
async {
printfn "Starting with %s..." s
let! result = Http.AsyncRequestStream(s)
use fileStream = new System.IO.FileStream(t,System.IO.FileMode.Create)
do! awaitTask (result.ResponseStream.CopyToAsync(fileStream))
printfn "Done with %s." s
}

let makeBatches n jobs =
let rec collect i jl acc =
match i,jl with
| 0, _ -> acc,jl
| _, [] -> acc,jl
| _, x::xs -> collect (i-1) (xs) (acc @ [x])
let rec loop remaining acc =
match remaining with
| [] -> acc
| x::xs ->
let r,rest = collect n remaining []
loop rest (acc @ [r])
loop jobs []


let download () =
downloadUrls
|> List.map fetchAndSave
|> makeBatches 2
|> List.iter (fun l -> l |> Async.Parallel |> Async.RunSynchronously |> ignore )
|> ignore

download()

注意 更新了代码,因此它一次创建 2 个下载批处理,并且只有第一个批处理有效。还添加了第一个答案中的 awaitTask,因为这似乎是正确的方法。

新闻 同样有趣的是:如果我中断停滞的脚本,然后将其再次 #load 到同一个 fsi.exe 实例中,它会立即停滞。我开始认为这是我使用的库中的错误或类似问题。

提前致谢!

最佳答案

此处的 fetchAndSave 已被修改为异步处理从 CopyToAsync 返回的任务。在您的版本中,您正在同步等待任务。当您使用 Async.RunSynchronously 运行整个工作流时,您的脚本似乎已锁定。但是,文件确实会在后台按预期下载。

let awaitTask = Async.AwaitIAsyncResult >> Async.Ignore

let fetchAndSave (s,t) = async {
let! result = Http.AsyncRequestStream(s)
use fileStream = new System.IO.FileStream(t,System.IO.FileMode.Create)
do! awaitTask (result.ResponseStream.CopyToAsync(fileStream))
}

当然还需要调用

do download()

在你脚本的最后一行让事情开始。

关于f# - 使用 fsharp.data.dll 和异步工作流停止 http 下载到磁盘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31265057/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com