f# - 使用异步工作流进行并行化的最佳实践

标签 f# asynchronous async-workflow

假设我想抓取一个网页,并提取一些数据。我很可能会写这样的东西:

let getAllHyperlinks(url:string) =
    async {  let req = WebRequest.Create(url)
             let! rsp = req.GetResponseAsync()
             use stream = rsp.GetResponseStream()             // depends on rsp
             use reader = new System.IO.StreamReader(stream)  // depends on stream
             let! data = reader.AsyncReadToEnd()              // depends on reader
             return extractAllUrls(data) }                    // depends on data
let!告诉 F# 在另一个线程中执行代码,然后将结果绑定(bind)到变量,然后继续处理。上面的示例使用了两个 let 语句:一个用于获取响应,一个用于读取所有数据,因此它至少会产生两个线程(如果我错了,请纠正我)。

尽管上面的工作流产生了几个线程,但执行顺序是连续的,因为工作流中的每个项目都依赖于前一个项目。在其他线程返回之前,实际上不可能进一步评估工作流程中的任何项目。

拥有多个 let! 有什么好处吗?在上面的代码中?

如果不是,如何更改此代码以利用多个 let!陈述?

最佳答案

关键是我们没有产生任何新线程。在整个工作流过程中,有 1 个或 0 个事件线程从 ThreadPool 中被消耗。 (一个异常(exception),直到第一个'!',代码在执行 Async.Run 的用户线程上运行。)“让!”在 Async 操作在海上时释放一个线程,然后在操作返回时从 ThreadPool 中拾取一个线程。 (性能)优势是对 ThreadPool 的压力较小(当然,主要的用户优势是简单的编程模型 - 比您编写的所有 BeginFoo/EndFoo/callback 内容好一百万倍)。

另见 http://cs.hubfs.net/forums/thread/8262.aspx

关于f# - 使用异步工作流进行并行化的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/496468/

相关文章:

f# - when 守卫是识别元组中的项目是否在模式匹配中具有相同值的唯一方法吗?

android - 'Future<dynamic >' has no instance getter ' body' 错误,当试图在 Flutter 中访问 Future SmsMessage 变量的主体时

postgresql - Postgres 异步创建表

c# - F# 中的异步工作流

asynchronous - 异步异常处理的意外行为,可能的错误?

f# - 如何在 F# 中异步下载网页并捕获错误

f# - 如何让 TypeProviders 在 Xamarin/Monodevelop 上工作

javascript - NodeJS 将 Promise 转换为 Promise.all

exception-handling - Async.Catch 对 OperationCanceledException 不起作用

c# - 如何解决类型约束不匹配,C# 到 F#