F#中的异步及并行模式(2):反馈进度的事件

在这篇文章中,我们将关注一个常见的异步模式:反馈进度的事件(Reporting Progress with Events)。在文章最后,我们会使用这个设计模式开发一个示例,从Twitter中获取一系列记录。

这是F#异步编程基础系列的第二部分。其中部分示例代码来自于F# JAOO Tutorial。

第1部分描述了F#作为一个并行及异步语言,是如何支持轻量级的响应操作,并给出了CPU异步并行和I/O异步并行两种模式。

第2部分便是本文。

第3部分则描述了F#中轻量级,响应式的独立代理对象。

模式3:反馈进度的事件

我们先来看一下这个设计模式的一个基础示例。在下面的代码中,我们会定义一个对象,以此来协调一组同时执行的异步任务。每个任务在结束之后会主动汇报它的结果,而不是等待统一的收集过程。

type AsyncWorker<'T>(jobs: seq<Async<'T>>) =

   // This declares an F# event that we can raise
   let jobCompleted = new Event<int * 'T>()

   /// Start an instance of the work
   member x.Start()  =
     // Capture the synchronization context to allow us to raise events back on the GUI thread
     let syncContext = SynchronizationContext.CaptureCurrent()

     // Mark up the jobs with numbers
     let jobs = jobs |> Seq.mapi (fun i job -> (job,i+1))

     let work =
       Async.Parallel
         [ for (job,jobNumber) in jobs ->
           async { let! result = job
               syncContext.RaiseEvent jobCompleted (jobNumber,result)
               return result } ]

     Async.Start(work |> Async.Ignore)

   /// Raised when a particular job completes
   member x.JobCompleted = jobCompleted.Publish

设计模式的一些关键之处已经使用黄色进行高亮:

在对象的Start方法中,我们在GUI线程中捕获了当前的“同步上下文”,这使得我们可以从GUI的上下文中运行代码或触发事件。我们还定义了一个私有的辅助函数来触发任意的F#事件,这虽不必须但可以使我们的代码变的更为整洁。

定义了多个事件。这些事件作为属性发布,如果该对象还需要被其他.NET语言使用,则为它标记一个[<CLIEvent>]属性。

我们这里通过指定一个定义了任务内容的异步工作流来启动后台任务。Async.Start可以用来启动这个工作流(虽然Async.StartWithContinuations更为常用,例如在后面的示例中)。在后台任务产生进度之后,便会在合适的时候触发这些事件。

这段代码使用了两个基于System.Threading.SynchronizationContext的辅助方法,它们会在这个系列的文章中多次出现。如下:

type SynchronizationContext with
   /// A standard helper extension method to raise an event on the GUI thread
   member syncContext.RaiseEvent (event: Event<_>) args =
     syncContext.Post((fun _ -> event.Trigger args),state=null)

   /// A standard helper extension method to capture the current synchronization context.
   /// If none is present, use a context that executes work in the thread pool.
   static member CaptureCurrent () =
     match SynchronizationContext.Current with
     | null -> new SynchronizationContext()
     | ctxt -> ctxt

时间: 2024-12-08 10:30:00

F#中的异步及并行模式(2):反馈进度的事件的相关文章

F#中的异步及并行模式(3

在本系列的第3部分中,我们会来探索F#中轻量级的,交互式的代理,以及与代理有关的一些模式,包括隔离的内部状态.(译注:由于原文内容较多,译文拆成两段进行.在上半段文章中讨论了代理的基本使用方式,而下半段则讨论关于代理使用中更进一步的模式.) 消息与联合类型 很多时候我们会使用联合类型(Union Type)作为消息的类型.例如,我将要展示一个基于代理的DirectX示例,我们要在模拟引擎中使用如下的消息: type Message = | PleaseTakeOneStep | PleaseAd

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

介绍 F#是一门并行(parallel)及响应式(reactive)语言.这个说法意味着一个F#程序可以存在多个进行中的运算(如使用.NET线程进行F#计算),或是多个等待中的回应(如等待事件或消息的回调函数及代理对象). F#的异步表达式是简化异步及响应式程序编写的方式之一.在这篇及今后的文章中,我会探讨一些使用F#进行异步编程的基本方式──大致说来,它们都是F#异步编程时使用的模式.这里我假设您已经掌握了async的基本使用方式,如入门指南中的内容. 我们从两个简单的设计模式开始:CPU异步

理解F#中的模式匹配与活动模式

模式匹配(Pattern Matching)允许我们根据标识符值的不同进行不同的运算,它通常被拿来跟C#中的if-else或switch语法结构相比较,结论往往是模式匹配比后者要更为灵活.强大.那先来分析一下它灵活.强大在哪儿. 为什么说模式匹配是灵活.强大的? 在我前面写过的几篇随笔里面,有几次提到了模式匹配,比如它能够对简单值(整数.字符串)匹配,也可以对.NET类型进行匹配,看下面两个简单的例子: F# Code - 对简单值和.NET类型进行匹配 // 对简单值进行匹配. let rec

.NET中的异步编程“.NET技术”:使用F#简化异步编程

不管是使用yield或借助第三方类库来简化异步编程,或多或少总是感觉不那么正统,有点hack的感觉.这种感觉在实验阶段倒还可以,要是用在产品中总有点担心,即使这些类库来自权威的第三方,我不知道大家有没有跟我同样的感觉.那么这个时候我们就会想,如果在语言中直接能提供这种机制该多好呢. F#的异步工作流 在Visual Studio 2010中,新包含了一种语言:F#.F#的一大特性就是异步计算.能让你用同步的方式编写异步的代码,不用使用AsyncCallback回调将一个方法分为两段,也不用注册异

.NET中的异步编程- IO完成端口以及FileStream.“.NET研究”BeginRead

写这个系列原本的想法是讨论一下.NET中异步编程风格的变化,特别是F#中的异步工作流以及未来的.NET 5.0中的基于任务的异步编程模型.但经过三篇文章后很多人对IO异步背后实现的原理以及为什么这样能提高性能很感兴趣.其实我本不想花更多的文字在这些底层实现的细节上,一来我并不擅长这些方面,二来我们使用.NET的异步IO就不需要关心这些底层东西,因为已经为你封装完备了.不过为了避免大家一再在这上面商讨,我还是在这个系列中间插入了一篇来解释一下. 本文我将从内核对象IO完成端口开始介绍,然后来瞧瞧.

.NET中的异步编程- IO完“.NET技术”成端口以及FileStream.BeginRead

写这个系列原本的想法是讨论一下.NET中异步编程风格的变化,特别是F#中的异步工作流以及未来的.NET 5.0中的基于任务的异步编程模型.但经过三篇文章后很多人对IO异步背后实现的原理以及为什么这样能提高性能很感兴趣.其实我本不想花更多的文字在这些底层实现的细节上,一来我并不擅长这些方面,二来我们使用.NET的异步IO就不需要关心这些底层上海企业网站制作东西,因为已经为你封装完备了.不过为了避免大家一再在这上面商讨,我还是在这个系列中间插入了一篇来解释一下. 本文我将从内核对象IO完成端口开始介

ASP.NET 2.0 中的异步页功能应用

asp.net|异步 下载本文源代码:WickedCode0510.exe ASP.NET 2.0 提供了大量新功能,其中包括声明性数据绑定和母版页,成员和角色管理服务等.但我认为最棒的功能是异步页,接下来让我告诉您其中的原因. 当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配给该线程.一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程用于处理其他请求.如果一个同步请求成为 I/O 绑定(例如,如果它调用一个远程 Web 服务或查询一个远程数据库,并等待调用

在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分

编程|网络|异步 ///////////////////////////////////////////////////////////////////////////////////////////* 标题:在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)----基础类库部分 当看到.NET中TcpListener和TcpClient的时候,我非常高兴,那就是我想要的通讯模式但是使用之后发现它们的力量太单薄了,我们需要一个更好的类库来替代它们. 下面提供了一些类,可以

F#中DSL原型设计:语法检查和语义分析

最近,人们对于领域特定语言F#中DSL原型设计的兴趣卷土重来.这些语言不仅能够为特定领域提供更好等级的提炼,从而有助于减少在通用语言中因低等级构造而造成的错误:而且通过提供额外配置.定制的业务逻辑等,它们为用户提供了一种有效的机制,用于细调你的应用程序.总之,DSL能够让你的应用程序更加多样化并具有更好的伸缩性. 大致来讲,领域特定语言的工作方式有两种--你可以通过对以源DSL编写的源文本进行转译来实施,或者通过将源文本编译为可执行代码.这两种方式都有着独特的优点和缺点.对于解释器和编译器的实施