假设我有这两个功能:
let dowork n =
async {
do printfn "work %d" n
}
let work i = async {
do! Async.Sleep(2000)
printfn "work finished %d" i }
Run Code Online (Sandbox Code Playgroud)
我如何使用Async.Parallel同时运行它们并在继续之前等待两者完成?
我花了很长时间才弄清楚为什么这段代码对某些网址"悬空":
let getImage (imageUrl:string) =
async {
try
let req = WebRequest.Create(imageUrl) :?> HttpWebRequest
req.UserAgent <- "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)";
req.Method <- "GET";
req.AllowAutoRedirect <- true;
req.MaximumAutomaticRedirections <- 4;
req.Timeout <- 3000; //HAHAHA, nice try!
let! response1 = req.AsyncGetResponse()
let response = response1 :?> HttpWebResponse
use stream = response.GetResponseStream()
let ms = new MemoryStream()
let bytesRead = ref 1
let buffer = Array.create 0x1000 0uy
while !bytesRead > 0 do
bytesRead := stream.Read(buffer, …Run Code Online (Sandbox Code Playgroud) 我正在尝试下载从我博客的xml备份中引用的3000多张照片.我遇到的问题是,如果其中一张照片不再可用,整个异步会被阻止,因为AsyncGetResponse不会超时.
ildjarn帮助我整理了一个版本的AsyncGetResponse,它在超时时失败了,但是使用它会产生更多的超时 - 就好像刚排队的请求超时一样.似乎所有的WebRequests都是"立即"启动的,唯一让它工作的方法是将超时设置为下载所有这些组合所需的时间:这不是很好,因为这意味着我已经调整了超时,具体取决于图像的数量.
我达到了香草的极限async吗?我应该考虑反应性扩展吗?
我想运行一些异步工作流,然后在打印一些结果之前等待它完成,例如:
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"
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我希望所有的dowork调用在打印"完成"之前完成.但是我得到这样的结果:
工作2工作3工作4工作5完成工作1
我尝试从creatework()中删除异步,但在运行异步工作流之前打印"已完成".
在真正的dowork中,程序会执行一些IO,所以我想在继续之前等待最慢的完成.
我在F#中创建了一个函数来从Yahoo恢复历史数据(F#的经典异步示例):
let getCSV ticker dStart dEnd =
async {
let query = getFileUrl ticker dStart dEnd
let req = WebRequest.Create(query)
use! resp = req.AsyncGetResponse()
use stream= resp.GetResponseStream()
use reader = new StreamReader(stream)
let content = reader.ReadToEnd()
let ts = parseData content
return ts
}
Run Code Online (Sandbox Code Playgroud)
现在,我可以通过执行以下操作异步运行此函数:
let test=
["MSFT";"YHOO"]
|>List.map (fun x -> getCSV x (DateTime.Parse("01.01.2000")) (DateTime.Parse("01.01.2010")))
|> Async.Parallel
|> Async.RunSynchronously
Run Code Online (Sandbox Code Playgroud)
好,这很酷.
现在,我想知道的是如何应用一些功能,这是价格的历史:
例如:
let getReturns (prices:(DateTime *float)list) =
[for i in 1..(prices.Length-1) -> i]
|> List.map (fun i ->(fst (List.nth …Run Code Online (Sandbox Code Playgroud)