我正在尝试下载从我博客的xml备份中引用的3000多张照片.我遇到的问题是,如果其中一张照片不再可用,整个异步会被阻止,因为AsyncGetResponse不会超时.
ildjarn帮助我整理了一个版本的AsyncGetResponse,它在超时时失败了,但是使用它会产生更多的超时 - 就好像刚排队的请求超时一样.似乎所有的WebRequests都是"立即"启动的,唯一让它工作的方法是将超时设置为下载所有这些组合所需的时间:这不是很好,因为这意味着我已经调整了超时,具体取决于图像的数量.
我达到了香草的极限async吗?我应该考虑反应性扩展吗?
我在这里有点沮丧.我知道我已经掌握了所有的东西,但我无法弄清楚如何将它们结合起来......
let saveImageToDisk path content =
async {
use s = new FileStream(path, FileMode.OpenOrCreate)
do! s.AsyncWrite(content)
printfn "Done writing %A" path
} // returns Async<unit>
let getImages imageUrls =
imageUrls
|> Seq.map (fun url -> topath url, getImage url)
//Next line not happy because content is Async<byte[]> instead of byte[]
|> Seq.map (fun (path, content) -> saveImageToDisk path content)
|> Async.Parallel
|> Async.RunSynchronously
Run Code Online (Sandbox Code Playgroud) 我有一些相当简单的F#异步代码从Wikipedia上下载了一百篇随机文章(用于研究).
出于某种原因,代码在下载期间的任意时间点挂起.有时它是在50之后,有时是在80之后.
异步代码本身非常简单:
let parseWikiAsync(url:string, count:int ref) =
async {
use wc = new WebClientWithTimeout(Timeout = 5000)
let! html = wc.AsyncDownloadString(Uri(url))
let ret =
try html |> parseDoc |> parseArticle
with | ex -> printfn "%A" ex; None
lock count (fun () ->
if !count % 10 = 0 then
printfn "%d" !count
count := !count + 1
)
return ret
}
Run Code Online (Sandbox Code Playgroud)
因为我无法通过fsi弄清楚问题是什么,所以我创建了WebClientWithTimeout,这是一个System.Net.WebClient允许我指定超时的包装器:
type WebClientWithTimeout() =
inherit WebClient()
member val Timeout = 60000 with get, set
override x.GetWebRequest …Run Code Online (Sandbox Code Playgroud)