【问题标题】:what is the relationship among different approaches of F# concurrencyF#并发的不同方法之间的关系是什么
【发布时间】:2014-12-29 18:09:45
【问题描述】:

我最近在学习 F# 异步工作流,这是 F# 并发的一个重要特性。让我感到困惑的是,有多少种方法可以在 F# 中编写并发代码?我读过除了 F#,还有一些关于 F# 并发的博客,我知道后台工作者之类的东西; IAsync结果;如果在本地机器上编程,F#中有分片内存并发;如果在分布式系统上编程,则存在消息传递并发。但我真的不确定这些技术之间有什么关系,以及如何对它们进行分类。我知道这是一个相当“大”的问题,不能用一两句话来回答,所以如果有人能给我具体的答案或推荐一些有用的参考资料,我将不胜感激。

【问题讨论】:

    标签: concurrency f#-async


    【解决方案1】:

    我对 F# 也很陌生,所以我希望能有更多的答案来补充这个 :)

    首先,您需要区分 .NET 类(可用于任何 .NET 语言)和 F# 独特方式来处理异步操作。在您提到的第一种情况以及其他情况下,您有:

    • System.ComponentModel.BackgroundWorker:这主要用于带有 Windows 窗体的第一个 .NET 版本中,不再推荐。

    • System.IAsyncResult:这也是一个由多个类(也是Task)实现的旧的.NET接口,但我通常不直接使用它。

    • Windows.Foundation.IAsyncOperation:另一个界面,但仅在 Windows 应用商店应用中使用。大部分时候直接翻译成Task,不用太担心。

    • System.Threading.Tasks.Task:这是现在处理 .NET 异步和并行(使用并行任务库)操作的推荐方法。这是 C# async/await 关键字背后的隐藏力量,它们只是将延续传递给任务的语法糖。


    所以现在有了 F# 的独特方式异步工作流MailboxProcessor。可以粗略的说,前者对应并行,后者对应并发。

    • Asynchronous Workflows:这只是一个计算表达式(又名 monad),它恰好处理异步:在后台运行的操作以防止阻塞 UI 线程或并行操作以在多核系统中获得最大性能。

      它或多或少等同于 C# async/await,但我们 F# 粉丝喜欢认为它是一个更优雅的解决方案,因为它使用更通用和灵活的机制(计算表达式),例如可以适应 asynchronous sequencesevents 甚至 Javascript callbacks。正如 Thomas Petricek 解释的那样,它还有其他优势here

      在大多数情况下,在异步工作流中,您将使用 Control.Async 中的方法或 F# 核心库中的 .NET 类扩展(如 WebRequest.AsyncGetResponse)。如有必要,您还可以直接与 .NET 任务(Async.AwaitTaskAsync.StartAsTask)交互,甚至可以使用 Async.StartWithContinuations 轻松创建自己的异步操作。

      要了解有关异步工作流的更多信息,您可以咨询MSDN documentation、宏伟的Scott Wlaschin's siteTomas Petricek's blogF# Wikibook

    • Control.MailboxProcessor:设计用于处理并发,即多个进程同时运行,通常需要共享一些信息。当多个线程同时尝试写入变量时,防止内存损坏的传统 .NET 方法是 lock 语句。除了函数式风格更喜欢使用不可变值这一事实之外,内存锁的正确使用也很复杂,并且还会有很高的性能损失。因此,MailboxProcessor 使用类似 Erlang 的基于消息(或基于角色)的并发方法来代替此方法。

      我自己使用MailboxProcessor的次数不多,但有关更多信息,您可以查看Scott Wlaschin's siteF# Wikibook


    我希望这会有所帮助!如果有人在此答案中看到不完全正确的内容,请随时对其进行编辑。

    干杯!

    【讨论】:

    • 是否还有其他语言使用类似的技术,例如 F# async wkf
    • 我不懂很多其他语言,所以我不确定,但显然所有现代语言都包含在非常基本的级别上处理异步的工具。如上所述,Erlang 有代理,EcmaScript 7 可能会包含来自 C# 的 async/await,而 Go 有本地通道。 Haskell 中的 Control.Concurrent.Async 库以与 F# 类似的方式使用 monad,而 Clojure 具有使用通道的 core.async。其中大多数背后的主要思想是,使用不可变数据可以更容易地推理异步操作。
    猜你喜欢
    • 2011-03-15
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 2012-01-30
    • 2012-08-12
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多