我有点了解F#中异步编程的语法。例如:
let downloadUrl(url:string) = async {
let req = HttpWebRequest.Create(url)
// Run operation asynchronously
let! resp = req.AsyncGetResponse()
let stream = resp.GetResponseStream()
// Dispose 'StreamReader' when completed
use reader = new StreamReader(stream)
// Run asynchronously and then return the result
return! reader.AsyncReadToEnd() }
在F#专家书籍(以及许多其他来源)中,他们说:
let! var = expr 简单地意味着“执行异步操作 expr 并在操作完成时将结果绑定到 var。然后继续通过执行计算体的其余部分来执行。”
我也知道,当执行异步操作时会创建一个新线程。我最初的理解是,在异步操作之后有两个并行的线程,一个执行 I/O,另一个同时继续执行异步体。
但在这个例子中,我感到困惑:
let! resp = req.AsyncGetResponse()
let stream = resp.GetResponseStream()
如果 resp
还没有开始,异步体中的线程想要 GetResponseStream
会发生什么?这可能会导致错误吗?也许我的最初理解是错误的。F# 专家书中引用的句子实际上意味着“创建一个新线程,挂起当前线程,在新线程完成后唤醒主线程并继续”,但在这种情况下我不认为我们能节省任何时间。
在最初的理解中,时间是通过在一个异步块中有多个独立的IO操作,从而可以在彼此干扰的情况下同时完成而节省的。但是在这里,如果我没有得到响应,我就不能创建流;只有当我拥有流时,我才能开始读取流。哪里节约了时间?