论道WP(三):应用程序栏
作者通过具体翔实的例子介绍了Winodws Phone 7中应用程序栏的使用方式。
该内容已经被标记书签!
标记书签错误,请重试!

作者 Ezra Zygmuntowicz 译者 苏锐 发布于 2007年9月17日
用Ruby on Rails开发各种类型的Web应用确实是很棒的选择,但是这些Web应用所在的问题领域中,你可能经常会遇到一些复杂精密的计算或者长时间运行的后台任务。但是由于你的Web应用被限制在 HTTP协议的request/response模型下,这可能就会造成一些问题。你知道应该如何运行漫长的后台任务而不让你的Web服务器超时么?你又知道该如何把这些任务的进度告诉用户么?
作者写了一个叫做BackgrounDRb的Rails插件用来解决上面的问题。在Ruby的标准库中已经预制了DRb(Distributed Ruby),为使用TCP/IP或Unix sockets通过网络存取Ruby对象提供了一个简单的API。BackgrounDRb提供了一个框架方便在Rails以外的独立线程中运行后台任务,从而摆脱了request/response模型。而且使用DRb你可以在Rails中使用钩子函数为用户提供任务进度或者状态更新。
BackgrounDRb服务端程序通过发布一个MiddleMan对象来管理你所有的woker类,其中包括一个由{job_key => running_worker_object}键值对组成的@jobs和一个由{job_key => timestamp}键值对组成的@timestamps两个hash,MiddleMan对象是DRb服务器和你的Rails应用之间的一个接口。下面的图表简单说明了BackgrounDRb和Rails应用之间的关系。
下面是通过插件提供的worker generator脚本生成的一个worker类。
$ script/generate worker Foo
class FooWorker < BackgrounDRb::Rails
def do_work(args)
# This method is called in its own new thread when you
# call new worker. args is set to :args
end
end
当FooWorker对象在Rails中通过MiddleMan初始化以后,do_work方法会自动运行在它自己的线程中。由于do_work在自己的线程中运行,所以Rails不需要等待do_work完成就可以继续执行。
使用BackgrounDRb,你经常会通过AJAX请求创建一个新的worker对象。在View中可以使用periodically_call_remote来取得任务的进度,再用你喜欢的方式展现给用户。接下来让我们补全刚才的 FooWorker类,并告诉你如何在一个rails controller中创建新的FooWorker对象并获取它的进度。
class FooWorker < BackgrounDRb::Rails
attr_reader :progress
def do_work(args)
@progress = 0
calculate_the_meaning_of_life(args)
end
def calculate_the_meaning_of_life(args)
while @progress < 100
# calculations here
@progress += 1
end
end
end
在controller中添加下面的代码:
class MyController < ApplicationController
def start_background_task
session[:job_key] =
MiddleMan.new_worker(:class => :foo_worker,
:args => "Arguments used to instantiate a new FooWorker object")
end
def get_progress
if request.xhr?
progress_percent = MiddleMan.get_worker(session[:job_key]).progress
render :update do |page|
page.call('progressPercent', 'progressbar', progress_percent)
page.redirect_to( :action => 'done') if progress_percent >= 100
end
else
redirect_to :action => 'index'
end
end
def done
render :text => "Your FooWorker task has completed
"
MiddleMan.delete_worker(session[:job_key])
end
end
再将下面的代码添加到你的start_background_task.rhtml视图中:
<%= periodically_call_remote(:url => {:action =>
'get_progress'}, :frequency => 1) %>
MiddleMan.new_worker方法会随机产生一个job_key,你可以把它存在session中方便存取。如果你想指定job_key的名字可以使用下面的方法:
# This will throw a BackgrounDRbDuplicateKeyError if the :job_key already exists.
MiddleMan.new_worker(:class => :foo_worker,
:job_key => :my_worker,
:args => "Arguments used to instantiate a new FooWorker object")
MiddleMan.get_worker :my_worker
BackgrounDRb安装之后还会生成一个配置文件RAILS_ROOT/config/backgroundrb.yml。里面有一个load_rails配置选项,如果设置为true你就可以在worker class中使用你的ActiveRecord对象了,在BackgrounDRb服务启动的时候会自动根据database.yml中的设置去访问数据库。
这个插件还可以用于缓存类似ActiveRecord object这类大对象或者需要大量计算的对象,你也可以把渲染后的View对象或者大的查询进行缓存,事实上你可以缓存任何文本和任何可以被序列华的对象。下面是一个使用缓存的例子:
# Fill the cache
@posts = Post.find(:all, :include => :comments)
MiddleMan.cache_as(:post_cache, @posts)
# OR
@posts = MiddleMan.cache_as :post_cache do
Post.find(:all, :include => :comments)
end
# Retrieve the cache
@posts = MiddleMan.cache_get(:post_cache)
# OR
@posts = MiddleMan.cache_get(:post_cache) { Post.find(:all, :include => :comments) }
MiddleMan.cache_get接受一个可选的block,如果缓存中的:post_cache是空的,block中的计算结果就会被放到cache中并赋给@post。 如果你没有提供block而且缓存是空的则返回nil。
在现在的实现中,你要自己负责对缓存过期,删除worker对象。有两种方法,一种是直接调用MiddleMan.delete_worker(:job_key)或者MiddleMan.delete_cache(:cache_key),也可以将一个时间对象传给MiddleMan.gc! ,删除所有在timestamp之前的jobs(文章开始提到MiddleMan包括@jobs和@timestamps两个hash)。下面的脚本可以删除30分钟以前的jobs,你可以把它放在cron中执行:
#!/usr/bin/env ruby
require "drb"
DRb.start_service
MiddleMan = DRbObject.new(nil, "druby://localhost:22222")
MiddleMan.gc!(Time.now - 60*30)
在最新的特性中会有一个定时机制加入到BackgrounDRb中,这将允许你定时的运行你自己的任务和垃圾回收,或者在你创建一个新的job或cache的时候就定义一个存活时间的参数。
插件中还包含了一些命令行脚本用于启动/停止 BackgrounDRb,在OS X、Linux或者BSD上面可以使用rake:
$ rake backgroundrb:start
$ rake backgroundrb:stop
在Windows上当你运行BackgrounDRb服务的时候要始终打开那个启动服务的命令行窗口(希望后面的版本可以有所改进)。所以在Windows上启动BackgrounDRb服务你要先打开一个命令行窗口,然后运行下面的命令:
> ruby script\backgroundrb\start
# ctrl-break to stop
现在你可能会问这东西在现实中究竟可以用在什么地方?在下面的列表中作者告诉了你,他正在用BackgrounDRb做什么:
作者在后续版本中还计划加入创建新进程的能力,以便能处理需要Ruby解释器实例的更大的任务。在Windows上希望可以作为service运行,希望熟悉Windows service的人能提供一些帮助,任何建议和补丁都非常欢迎。
东西不错,不过应用场景不是特别大,对实时性要求不高的东西根本用不上,在*nix下可以用cron,win下可以用at来定时执行指定的任务,基本上可以满足要求了。
------------------------------------------
[Ruby中文社区] - ruby-lang.org.cn
在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,本文详细介绍了Java SE1.6中对于锁的性能优化,以及锁的存储结构及升级过程。
本次分享将首先介绍现代富文本编辑器的组成和实现,然后结合UEditor的开发过程,与参会者分享UEditor在设计和实现的过程中,所涉及到的核心功能的细节实现。
本次演讲视频录制于百度技术沙龙。
我们所开发的应用程序大多都需要提供一个图形用户界面(GUI)。关于GUI应用的架构设计,已经有了Form & Control、MVC,、MVP、 Passive View等多种模式。模式可以帮助我们建立优雅的架构,但前提是弄清楚模式的应用场景。弄清楚GUI应用面临的设计上的问题,有助于我们正确的挑选设计方案。
MongoDB是一种非常易用的NoSQL方案,Brian C. Dilley在这篇文章里介绍了MongoDB的优劣势,并介绍了MJORM项目。MJORM用于MongoDB,是一个没有注解的Java ORM库。
随着网络基础设施的逐步成熟,从RPC进化到Web Service,并在业界开始普遍推行SOA,再到后来的RESTful平台以及云计算中的PaaS与SaaS概念的推广,分布式架构在企业应用中开始呈现出不同的风貌,然而殊途同归,这些分布式架构的目标仍然是希望回到建造巴别塔的时代,系统之间的交流不再为不同语言与平台的隔阂而产生障碍。
精益软件开发方法因其对市场和交付的重视和在各种场景下体现出的适应能力正在获得广泛的关注。特别是在精益创业(Lean Startup)渐渐兴起和技术日新月异的今天,其"极端"的思想也变得越来越必要和可行。 InfoQ就此主题对他做了深入的采访。
1 条回复
关注此讨论 回复