您的位置:首页 > 编程语言

13.1.4 创建工作流基本操作

2017-01-12 20:45 204 查看
13.1.4 创建工作流基本操作

F# 功能包(PowerPack)提供了许多重要 I/O 操作的异步版本,但是不全,为此,F# 库提供了构建自己的工作流基本操作的方法。如果操作在工作流中运行,使用的标准 .NET 模式,提供 BeginOperation 和 EndOperation 方法,可以使用 Async.FromBeginEnd 方法,把这两个方法作为参数,就会返回异步工作流。

能够执行而不会阻塞线程的其他操作也可以。例如,我们可能要等待一个特定事件发生,当它触发时,继续执行工作流。清单 13.4 创建一个基本操作,使用计时器,等待一定的时间(毫秒数),然后启动工作流。

清单 13.4 执行异步等待 (F# Interacitve)

module MyAsync =

let Sleep(time) = [1] <– 暂停工作流一定的时间

Async.FromContinuations(fun (cont, econt, ccont) –>

let tmr = new System.Timers.Timer(time, AutoReset = false)

tmr.Elapsed.Add(fun _ -> cont()) [2] <– 启动计算

tmr.Start()

);;

(…)

Async.RunSynchronously(async {

printfn “Starting…”

do! MyAsync.Sleep(1000.0) [3] <– 等待但不阻塞线程

printfn “Finished!”

});;

Starting…

Finished!

val it : unit = ()

F# 库中已经有同样的功能了,由 Async.Sleep 实现,在本章后面我们会用到它,因此,这仅是一个示例而已;如果使用同步版本 Thread.Sleep,就会阻塞工作流,这是一个重要区别。在我们的函数创建计时器,把线程返回到 .NET 线程池期间,这个方法会一直阻塞线程。而使用我们的基本操作时,.NET 运行时可以并行执行工作流,而不受任何限制。

Sleep 函数[1],其参数为想要延迟处理的毫秒数,使用 Async.FromContinuations 方法构建工作流。这个方法非常接近地反映了工作流的内部结构。参数值是 lambda 函数,在工作流启动时执行。Lambda 的参数为有三个连续的元组,第一个函数在操作成功完成时调用,第二个连续在操作触发异常时调用,类似于前面补充材料中声明的 Async<’T> 类型,第三个连续在取消工作流时触发。在 lambda 函数体中,我们创建一个计时器,指定 Elapsed 事件的处理程序,这个处理程序只运行成功连续[2]。

清单 13.4 表明,创建了自己的基本操作以后,使用它的代码非常简单。因为返回 unit 值,我们用 do! 基本操作,而不是 let! [3]。当代码执行时,它构造了有处理程序的计时器,然后启动;当指定的时间过去,系统从线程池取得一个可用的线程,运行事件处理程序,依次执行计算的其余部分(在本示例,输出到屏幕)。

C# 中的异步工作流

简化 C# 中的异步编程,已经有过无数的尝试,但是,仍没有能够像异步工作流语法一样完美的库。从最终用户的角度来看(只是把代码包装在 async 块中),F# 语法是非常简单的,而这在 C# 中是很难实现的。

我们已经看到过,LINQ 查询大体相当于 F# 的计算表达式,所以,你可能会忍不住要实现 Select 和 SelectMany 操作。理论上,使用查询表达式,写出异步操作是有可能的,但是,能够在查询内部使用的语法,是有限制的。值得关注的是,C# 迭代器也可以用于此目的。《在 C# 中使用迭代器的异步编程》一文对这种方法有叙述(在 http://tomasp.net/blog/csharpasync.aspx)。使用这种技术最实用的库是 Jeffrey Richter 的 PowerThreading 库 [Richter,2009年]。

基于 C# 迭代器、最复杂的一个库,是并发性和协调运行库(CCR)[Chrysanthakopoulos 和 Singh,2005年]。这个库是为微软机器人工作室(Microsoft Robotics studio)而开发的一部分,在这里,响应性和异步处理能力,对任何应用程序都是至关重要的。可以在 Jeffery Richter 的文章《并发事务》中找到有关这个库的详细内容[Richter,2006年]。

现在,可以开始把异步工作流用于更具体的目的了。在下一节,我们将会看到由世界银行所提供的数据服务,讨论如何使用异步工作流来调用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  异步 F# 函数编程
相关文章推荐