F#中的异步和并行设计模式(一):并行CPU和I/O计算

F#语言程序设计 立即下载

在F#中的异步和并行设计模式:并行化的CPU和I/O计算

F#是一种并行地、交互式的语言。在这点上,我们的意思是:运行F#程序既能有多个实时的赋值(例如:.NET线程主动计算F#的结果)又能有多个等待的响应(例如:等待对事件和消息作出响应的回调和代理)。

编写并行和交互式程序的一个简单方法是使用F#异步表达式。在这篇和接下来的文章中,我将向你介绍F#异步编程的一些基本方法---- 粗略地讲,这些就是通过F#异步编程实现的设计模式。我假设你已经知道了异步的基本知识,如果还不清楚请看这样的入门指南。

我们用两个简单的设计模式来开始介绍:并行CPU 异步处理和并行I/O 异步处理

第三部分介绍了F#中的轻量级代理、交互式代理、孤立式代理。

模式1: 并行的CPU 异步处理

让我们看看第一个模式的一个例子:并行CPU 异步处理,也就是并行运行一系列受中央处理机限制的计算。下面的代码是计算斐波那契函数与并行计算的时间表。

let rec fib x =if x <= 2then 1elsefib(x-1) + fib(x-2)
let fibs =
    Async.Parallel[ for i in 0..40 -> async { return fib(i) } ]
    |> Async.RunSynchronously

运行的结果是:

val fibs : int array =

[|1; 1; 2; 3; 5; 8; 13; 21; 34; 55; 89; 144; 233; 377;610; 987; 1597; 2584;

4181; 6765; 10946; 17711; 28657; 46368; 75025; 121393;196418; 317811;

514229; 832040; 1346269; 2178309; 3524578; 5702887; 9227465;14930352;

24157817; 39088169; 63245986; 102334155|]

上面的示例代码指出了并行CPU 异步处理模式的要素:

a. “async{…}”是用来指定CPU的一些任务数。

b.  这些通过fork-join机制与Async.Parallel融合到并行中去

在这种情况下,使用Async.RunSynchronously来执行该组合,即启动一个异步实例并同步等待整体的结果。

您可以在很多日常的CPU并行工作(如分割和并行矩阵乘法)和批处理作业中使用这种模式。

模式2:并行I/O 异步处理

到目前为止,我们只看到与F#有关的受中央处理机限制的并行编程。关于F#异步编程很重要的一点是您可以用它来进行CPU和I/O计算。这带来了我们的第二种模式:并行I/O 异步处理,如并行进行I/O操作(又称为重叠I/O)。例如,下面的代码并行地请求多个网页以及为每一个请求提供响应,并返回所收集的结果。

open System
open System.Net
open Microsoft.FSharp.Control.WebExtensions

let http url =
    async { let req = WebRequest.Create(Uri url)
            use! resp = req.AsyncGetResponse()
            use stream = resp.GetResponseStream()
            use reader = new StreamReader(stream)
            let contents = reader.ReadToEnd()
            return contents }

let sites = ["http://www.bing.com";
             "http://www.google.com";
             "http://www.yahoo.com";
             "http://www.search.com"]

let htmlOfSites =
   Async.Parallel [for site in sites -> httpsite ]
    |>Async.RunSynchronously

上面的代码指出了并行I/O 异步处理模式的本质:

(a)”async{…}”是用来编写包括一些异步I/O的任务。

(b)这些通过fork-join组合Async.Parallel融合到并行中去

在这种情况下,使用Async.RunSynchronously执行的组件,同步等待整体的结果。

使用let!(或与其等价的资源处理命令use!)是组成asyncs的一个基本途径。像这样的一行代码:

let! resp = req.AsyncGetResponse()

当HTTP GET的响应发生时,会产生一个“响应”。也就是说当AsyncGetResponse操作完成时,剩下的async{…}代码块会运行。然后,在等待这个响应的过程中,既没有.NET也没有操作系统的线程被阻塞,因为只有活动的CPU计算才使用一个底层的.NET或者O/S线程。相比之下,响应等待的代价(如回调,事件处理程序和代理)是相对便宜的,通常情况下就像单个的注册对象那么便宜。因此你可以拥有数千甚至上百万的响应等待。例如,一个典型的GUI应用程序有许多注册的事件处理函数,一个典型的网络爬虫为每一个重要的web请求提供一个注册的处理函数。

在上面,“use!”代替”let!”表示跟web请求相关的资源应该在变量作用域结束后被释放掉。

有关I/O并行化的好处之一是缩放。随着多核的受CPU限制的编程,如果你在一台多核的机器上付出足够多的努力,经常会有2倍、4倍或8倍的加速。你可以用I/O的并行编程进行成百上千的并行操作(虽然实际并行取决于你的操作系统和网络连接)来10倍、100倍、1000倍或更多倍地提高速度,甚至在一个单核的机器上。例如,这个使用F# 异步处理的漂亮的例子,最后被一个Iron Python应用程序调用。

许多现代应用程序是受I/O限制的,所以重要的是能够在实践中识别和运用这种设计模式。

在GUI线程上启动,在GUI线程上结束。

这两个设计模式有一个重要的变化,这就是用Async.StartWithContinuations代替Async.RunSynchronously。这里,你指定三个函数分别在异步线程成功结束、失败结束或取消结束时作为并行线程组运行。

每当你面临“我需要得到一个异步的结果,但我真不想使用RunSynchronously”这样问题的时候,那么你应该考虑:

a.      通过let!或use!把这个异步代码块作为一个更大的异步代码的一部分来开始,或者

b.     用Async.StartWithContinuations 来开始这个异步程序

Async.StartWithContinuations在GUI线程上进行异步执行时是非常有用的,因为你永远也不会希望去阻止这个GUI线程,相反,你想在异步完成时安排发生一些GUI的更新。例如,在F# JAOO 教程代码中的BingTranslator示例就是这样用的。在这个博客帖子的底部,给出了此示例的完整版,这里最重要的是要注意到当“翻译”按钮被按下时会发生什么:

button.Click.Add(fun args ->
    let text = textBox.Text
    translated.Text <-"Translating..."
    let task =
        async { let! languages = httpLines languageUri
                let! fromLang = detectLanguage text
                let! results = Async.Parallel [for lang in languages ->translateText (text, fromLang, lang)]
                return (fromLang,results) }
    Async.StartWithContinuations( 
        task,
        (fun (fromLang,results) ->
            for (toLang, translatedText) in results do
                translated.Text <-translated.Text + sprintf "\r\n%s --> %s:\"%s\"" fromLang toLang translatedText),

        (fun exn -> MessageBox.Show(sprintf"An error occurred: %A" exn) |> ignore),
        (fun cxn -> MessageBox.Show(sprintf"A cancellation errorocurred: %A" cxn) |> ignore)))

在高亮部分,指定了这个异步处理的内容,它包括使用Async.Parallel把输入的文本并行地翻译成多国语言。这里的复合异步是用Async.StartWithContinuations启动的,这会使异步线程在它首次运行I/O操作时尽可能快地被疏导,同时指定三个函数分别在异步线程成功结束、失败结束或取消结束时运行。这里是任务结束时的一张截图(关于翻译的准确性不能保证)

  图片===

Async.StartWithContinuations 有一个很重要的属性 ——如果异步开始于GUI线程(例如:一个非空的SynchronizationContext.Current线程),那么结束函数会在这个GUI线程上被调用。这确保了结果更新的安全。F# 异步类库允许你指定要合成的I/O任务,然后在GUI的线程上运行,这样就不必在后台的线程中配置你的更新了,我们将在接下来的帖子中解释这个话题。

关于Async.Parallel的工作机制需要注意的地方:

·        在运行时,组成异步处理的Async.Parallel最初是通过一个请求计算队列开始的。和大部分异步处理类库一样,最终这些操作会使用QueueUserWorkItem。使用多个队列也是可以的,我们会在接下来的帖子中讨论到。

·        Async.Parallel并没有什么特别神秘的:你可以用位于Microsoft.FSharp.Control.Async类库中的其他基本函数(如Async.StartChild)来自定义以不同异步方式协作的异步处理机制。我们会在以后的帖子中再来讨论这个话题。

更多示例:

F#JAOO教程中使用了这些模式的例子:

·        BingTranslator.fsx 和BingTranslatorShort.fsx:用F# 调用一个REST API.这与任何类似的基于web的HTTP服务相似。这个示例的版本在下面已经给出。

·        AsyncImages.fsx:并行磁盘I/O和图形处理

·        PeriodicTable.fsx:调用一个web service,获取并行的原子量(元素表)

并行计算的局限性:

这里介绍的两大并行模式有一些局限性。值得注意的是,一个由Async.Parallel产生的异步线程在运行的时候是无法交互的——例如,它不报告进度或部分结果。为了打破这样的局限,我们需要另外建立一个可交互的对象来触发部分操作完成事件。我们会在接下来的文章中关注这个的设计模式。

另外,Async.Parallel只处理固定数量的作业。在后面的文章中,我们会看到很多这样的例子——作业被当作工作进程而生成。换一种方式来看待这个局限性,就是:Async.Parallel产生的异步不立即接受传入的信息。既:它不是一个进度可以被驾驭的代理,除了取消。

由Async.Parallel生成的异步操作确实支持取消。除非所有的子任务已经完成或者已被有效取消掉,否则取消是无效的。这通常是你想要的。

结论:

并行CPU异步操作和并行I/O异步操作模式可能是F# 异步编程中最简单的两种设计模式。通常情况下,简单的东西是重要的和功能强大的。请注意,这两个模式的唯一不同点在于并行I/O模式使用的异步处理包含了(而且往往占主导地位)I/O请求,加上一些CPU 处理创建请求对象并做后期处理。

在将来的博客中,我们将关注其他有关并行和交互的F#异步编程的设计话题, 包括:

·        从GUI线程启动异步操作

·        定义轻量级的异步代理

·        定义使用异步操作的后台工作组件

·        使用异步创建.NET任务

·        使用异步操作创建.NET APM(Asynchronous Programming Model异步编程模块)模式

·        取消异步操作

 

BingTranslator 代码示例

下面是BingTranslator示例的代码。 你需要一个Live API 1.1 AppID来运行它。

(注意:这个例子可能需要为Bing API 2.0做适度的调整,特别是语言检测的API在2.0不存在,然而,这些代码应该还是可以作为一个好的指导)

open System
open System.Net
open System.IO
open System.Drawing
open System.Windows.Forms
open System.Text
  
/// A standard helper toread all the lines of a HTTP request. The actual read of the lines is
/// synchronous once theHTTP response has been received.
let httpLines (uri:string) =
  async { let request = WebRequest.Createuri
          use! response = request.AsyncGetResponse()         
          use stream = response.GetResponseStream() 
          use reader = new StreamReader(stream) 
          let lines = [ while not reader.EndOfStream do yield reader.ReadLine() ]
          return lines }

type System.Net.WebRequest with  
    /// An extension member to write content into anWebRequest.
    /// The write of the content is synchronous.
    member req.WriteContent (content:string) = 
        let bytes =Encoding.UTF8.GetBytes content
        req.ContentLength <- int64bytes.Length
        use stream =req.GetRequestStream()
        stream.Write(bytes,0,bytes.Length)  
  
    /// An extension member to read the content from aresponse to a WebRequest.
    /// The read of the content is synchronous once theresponse has been received.
    member req.AsyncReadResponse () =
        async { use! response = req.AsyncGetResponse() 
                use responseStream = response.GetResponseStream() 
                use reader = new StreamReader(responseStream)
                return reader.ReadToEnd() }

#load @"C:\fsharp\staging\docs\presentations\2009-10-04-jaoo-tutorial\BingAppId.fs"
//let myAppId ="please set your Bing AppId here"   
/// The URIs for the RESTservice we are using
let detectUri       = "http://api.microsofttranslator.com/V1/Http.svc/Detect?appId=" + myAppId
let translateUri    = "http://api.microsofttranslator.com/V1/Http.svc/Translate?appId=" + myAppId +"&"
let languageUri     = "http://api.microsofttranslator.com/V1/Http.svc/GetLanguages?appId=" + myAppId
let languageNameUri = "http://api.microsofttranslator.com/V1/Http.svc/GetLanguageNames?appId=" + myAppId

/// Create the userinterface elements
let form       = new Form (Visible=true, TopMost=true, Height=500, Width=600)
let textBox    = newTextBox (Width = 450, Text ="Enter some text",Font =newFont("Consolas", 14.0F))
let button     = newButton (Text="Translate", Left = 460)
let translated = newTextBox (Width = 590,Height = 400, Top = 50, ScrollBars = ScrollBars.Both, Multiline = true, Font=new Font("Consolas", 14.0F))
form.Controls.Add textBox
form.Controls.Add button
form.Controls.Addtranslated

/// An async method tocall the language detection API
let detectLanguage text =
  async { let request = WebRequest.Create(detectUri, Method="Post", ContentType="text/plain")
          do request.WriteContent text
          return! request.AsyncReadResponse() } 

/// An async method tocall the text translation API
let translateText (text,fromLang, toLang) =
  async { let uri = sprintf "%sfrom=%s&to=%s" translateUri fromLangtoLang
          let request = WebRequest.Create(uri, Method="Post", ContentType="text/plain")
          request.WriteContent text
          let! translatedText =request.AsyncReadResponse()
          return (toLang, translatedText)}  

button.Click.Add(fun args ->   
    let text = textBox.Text
    translated.Text <- "Translating..."   
    let task =
        async { /// Get the supportedlanguages
                let! languages = httpLineslanguageUri
                /// Detect the language ofthe input text. This could be done in parallel with the previous step.
                let! fromLang = detectLanguagetext
                /// Translate into eachlanguage, in parallel 
                let! results = Async.Parallel [for lang in languages -> translateText (text,fromLang, lang)]
                /// Return the results
                return (fromLang,results)} 

    /// Start the task. When it completes, show theresults.
    Async.StartWithContinuations( 
        task,
        (fun (fromLang,results) ->
            for (toLang, translatedText) in results do
                translated.Text <- translated.Text +sprintf "\r\n%s --> %s: \"%s\"" fromLang toLang translatedText),
        (fun exn -> MessageBox.Show(sprintf "An error occurred:%A" exn) |> ignore),
        (fun cxn -> MessageBox.Show(sprintf "A cancellationerror ocurred: %A" cxn) |> ignore)))
 

 原文链接:http://blogs.msdn.com/b/dsyme/archive/2010/01/09/async-and-parallel-design-patterns-in-f-parallelizing-cpu-and-i-o-computations.aspx

 

安川机械手FS100中文手册 安川机械手控制器FS100中文使用手册,包括机械手控制器的设置及其编程等等 立即下载

相关推荐

Qoder Quest 模式实战:从需求到代码的自动化开发

本文深入探讨Qoder Quest模式如何实现从需求到代码的自动化开发。通过编写清晰的Spec规格说明,Qoder能智能分解任务并在后台执行,生成高质量代码,大幅提升开发效率,让开发者专注于架构设计等创造性工作。

herb5的博客 1152

F#程序设计语言初步

F#,印度数学教育与优秀编程F#(发音为F sharp)是一种基于OCaml的函数式程序设计语言,它由微软研究院设计。运行它所需的所有工具可从微软免费获得。F#可以在.NET CLR中运行,这意味着它可用于现存的.NET项目。此外,它还可以利用所有其它.NET代码。它克服了函数式程序设计语言的传统弱点,如缺少库函数,使用工具和开发环境等。F#语言可以独立使用,但也...

weixin_30478757的博客 171

Ubuntu22.04中通过conda快速部署PyTorch开发环境(CPU/GPU双版本实战)

本文详细介绍了在Ubuntu22.04系统中,如何利用Conda高效部署PyTorch开发环境。文章分别提供了CPU与GPU双版本的实战教程,涵盖环境创建、镜像加速、版本匹配及深度验证等关键步骤,旨在帮助开发者快速搭建稳定、兼容的深度学习环境,从而专注于模型开发。

rose2的博客 556

F#程序设计-F#语言基础之剖析一个F#程序

现在,通过前面的系列介绍,你可能想知道怎么把在FSI交互中的输入的F#代码转换成一个F#程序,但事实上,你在前看看到的每个每个代码片段都是一个全面的项目。大多数其他语言,如C#,需要一个明确的程序入口点,通常称为main方法,然而我们的F#程序迄今尚未定义任何特殊的标记,表明该程序应开始,在F#,单文件应用中代码文件的内容执行顺序是从上到下的,这个跟C语言有点类似,就是如果在一个函数中调用本代

AAAA的专栏 791

PCB工程师必看:别再搞错1078玻纤布的Dk了,手把手教你算等效介电常数

本文为PCB工程师提供了1078玻纤布等效介电常数(Dk)的详细计算指南,帮助解决高速设计中的信号完整性问题。通过解析玻纤布结构、混合介质理论和实战计算方法,指导工程师准确设置EDA工具参数,避免常见的Dk计算误区,提升设计精度和仿真准确性。

weixin_42546392的博客 399

chipseeker Y叔

这一次讲解非常重要的peak注释,注释在ChIPseeker里只需要用到一个函数annotatePeak,它可以满足大家各方面的需求。 输入 当然需要我们上次讲到的BED文件,ChIPseeker自带了5个BED文件,用getSampleFiles()可以拿到文件的全路径,它返回的是个named list,我这里取第4个文件来演示。annotatePeak的输入也可以是GRanges对象,你如果用R做peak calling的话,直接就可以衔接上ChIPseeker了。 require(ChIPseeke

生信小博士的博客 1589

F#中的异步及并行模式(1):并行CPU及I/O计算

最后还是忍不住翻译文章了。这系列的文章谈论的是F#中常见的异步及并行模式,作者为F#语言的主要设计者Don Syme。异步相关的编程是F#语言中最重要的优势之一(我甚至在考虑“之一”两个字能否去掉)。F#是一门非常有特色的语言,是一门能够开阔眼界,改变您编程思路的语言,它经过了几年设计以及多个预览之后终于要正式露面了——此刻不上,更待何时。 介绍 F#是一门并行(parallel)及响应式(r...

weixin_34220179的博客 207

S32DS新建工程、编译调试下载、导入工程详细介绍

新建了一个工程之后,下面简单介绍下基本的UI界面。其中最左下角那个是界面,这个界面很重要,是图形化配置界面,然后可以根据这些配置自动生成代码。其中,左边那些配置文件,都是系统帮我们创建好了的,我们其实可以直接用就行。有PE工具的调试,以及Jlink工具的调试。我目前使用到PE工具调试可以查看寄存器值,而Jlink调试查看不了寄存器值。连接了开发板之后,点击Debug就可以吧程序下载到芯片上了,而且可以进入到调试界面。

luobeihai的博客 2万+

F#中的异步及并行模式(3 - 上):代理的基本使用

在本系列的第3部分中,我们会来探索F#中轻量级的,交互式的代理,以及与代理有关的一些模式,包括“隔离的内部状态”。(译注:由于原文较长,因此译文分为两段,目前是第一段,讲解了F#中异步代理的基本使用方式。) 第1部分描述了F#作为一个并行及异步语言,是如何支持轻量级的响应操作,并给出了CPU异步并行和I/O异步并行两种模式。 第2部分描述了如何从异步计算或后台计算单元中获得结果。 模式4...

weixin_34007879的博客 142

DAC8568实战指南:如何用STM32实现8通道DAC精准控制(附代码)

本文提供DAC8568与STM32结合的实战指南,详细解析8通道16位DAC的精准控制方法。内容涵盖硬件连接、SPI配置、驱动层构建、时序调试及多通道同步输出等关键步骤,并附有经过验证的HAL库驱动代码,帮助工程师快速解决实际项目中的通信与输出稳定性问题。

weixin_29175469的博客 745

ComfyUI整合包V8中文版最新版介绍

和普通AI绘图网页不同,它把图像生成的每一个步骤拆分成一个个"节点",用连线把它们串起来,形成工作流。里面包含ComfyUI内核、Python运行环境、常用插件、部分预置模型,还有一个叫"绘世启动器"的图形界面管理工具。网上的对比数据显示,WebUI最低需要4G显存,ComfyUI最低3G显存就能运行。可以在里面管理插件、切换模型路径、设置显存模式、查看日志报错,还有"疑难解答"功能,遇到报错可以先扫描一下看是不是已知问题。原版ComfyUI的界面是英文的,右键菜单、节点名称全是英文。

欢迎来到鸾姝淡月博客,专为程序员和编程爱好者打造的技术博客。我们分享编程语言趋势、开发工具、编程哲学、职业发展等,助你掌握新技术,优化技能,激发编程热情。 5227

F#语言的并发编程

F#是一种函数式编程语言,它运行在.NET环境中,支持面向对象和命令式编程风格。F#具有强类型系统和类型推导,能够很好的处理不可变数据结构,这使得并发编程变得更加容易。在F#中,所有的数据都是不可变的,这意味着一旦创建,就不能被修改,这有助于减少多个并发执行的任务之间的干扰。F#语言提供了强大的并发编程能力,使得我们可以轻松地处理并发和并行计算。异步工作流、邮件盒以及并行集合等特性为开发高效、响应迅速的应用提供了便利。在实际应用中,我们可以将这些技术结合起来,构建高性能的系统。

2501_91366782的博客 399

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

在F#中的异步和并行设计模式

在F#中的异步和并行设计模式:并行化的CPU和I/O计算 F#是一种并行地、交互式的语言。在这点上,我们的意思是:运行F#程序既能有多个实时的赋值(例如:.NET线程主动计算F#的结果)又能有多个等待的响应(例如:等待对事件和消息作出响应的回调和代理)。 编写并行和交互式程序的一个简单方法是使用F#异步表达式。在这篇和接下来的文章中,我将向你介绍F#异步编程的一些基本方法---- 粗略地讲,这...

weixin_30526593的博客 102

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

F#中的异步和并行设计模式(三):代理

在这个系列的第三部分,我们解释了F#中的轻量级代理的和交互式代理,并且看过了一些与之相关的典型的设计模式,包括内部隔离状态。 第一部分分描述了F#是一种并行交互式语言及如何支持轻量级交互操作的,并且为并行CPU异步处理和并行I/O异步处理两种模式作了诠释。 第二部分描述了一种通过触发事件提交部分结果的模式。   模式4——你的第一个代理 让我们看看你的第一个异步代理。

fsharp_net的专栏 1135

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

F#语言的网络延迟优化

网络延迟是指数据从源端传输到目的端所需的时间。传输延迟:数据在传输介质中传播所需的时间。处理延迟:数据在网络设备(如路由器、交换机)中处理所需的时间。排队延迟:数据在网络设备中排队等待处理的时间。传播延迟:数据在物理介质中传播所需的时间。F#语言凭借其强大的函数式编程能力和高效的并发处理能力,在网络延迟优化方面具有显著优势。通过使用F#的异步编程模型、并行计算和轻量级线程,可以显著降低网络延迟,提高系统响应速度和并发处理能力。

2501_90990402的博客 884

F#并行相关资料

https://blogs.msdn.microsoft.com/dsyme/2010/01/09/async-and-parallel-design-patterns-in-f-parallelizing-cpu-and-io-computations/

qq_24920947的博客 218

F#中的异步和并行设计模式(二):用事件触发来报告进度

在这篇文章中,我们将着眼于一个常用的异步设计模式,我叫它用事件触发来报告进度。在这篇文章后面,我们将使用这种设计模式从推特上抽样读取帖子流。 这是F#异步编程基础技术系列的第二部分,这里有些例子的代码是摘自F# JAOO 教程。 ·第一部分描述了F# 通过支持轻量级交互是一种怎样的并行和交互式语言,并且介绍了 并行CPU异步处理和并行I/O异步处理模式。 ·第...

weixin_34061555的博客 85
上一篇: F# 3.0 BUILD讲座的示例代码
下一篇: 设计模似和F#相关资料的一些链接
fsharp_net
博客等级 码龄15年 20粉丝 17原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值