2012-07-15 72 views
2

在过去的12个小时里,我一直关注这个主题,而且我根本无法找到任何地方。我甚至不知道这是否可行,但我希望这是因为它将继续我的项目很长的路要走。协程,Lua中的多个请求

我试图做的是创建协程,所以我使用的特定程序不能冻结,因为它无法执行异步http请求。尽管我对协程的理解仍然在“嗯?这是如何工作的?”我已经想出了如何做到这一点。相。我现在的问题是能够用正确的信息来响应多个请求。例如,下面的应该产生三个独立的反应:

foo(a) 
foo(b) 
foo(c) 

其中foo启动与内部参数的协程。如果全部请求分开,那么它返回正确的结果。但是,如果作为一个块申请,它只会返回foo(c)的结果。现在,我明白这背后的推理,但我无法找到一种方法,让它在被请求作为块时返回所有三个结果。为了帮助理解这个问题了一下,这里的实际代码:

function background_weather() 
local loc = url.escape(querystring) 
weatherpage = http.request("http://api.wunderground.com/api/004678614f27ceae/conditions/q/" .. loc .. ".json") 
wresults = json.decode(weatherpage) 
--process some stuff here, mainly datamining 
end 
--send datamined information as a response 
coroutine.yield() 
end 

而且协程的创建:

function getweather() 
-- see if backgrounder running 
    if background_task == nil or 
    coroutine.status (background_task) == "dead" then 
-- not running, create it 
    background_task = coroutine.create (background_weather) 
-- make timer to keep it going 
AddTimer ("tickler", 0, 0, 1, "", 
      timer_flag.Enabled + timer_flag.Replace, 
      "tickle_it") 
    end -- if 
end -- function 

querystring变量被设置与初始请求。我没有在这里包括它,但为了测试,使用12345作为querystring变量。定时器是脚本原始作者初始化的东西,用于检查协程是否仍在运行,每秒都会触发背景,直到完成。说实话,我甚至不确定我是否正确地做了这件事,尽管它似乎在程序中异步运行。

那么,是否有可能在一个模块中接收多个请求并正确返回多个响应?或者,这对Lua来说是一项太多的任务吗?

回答

1

在Lua编程Chapter 9.4包含如何处理这个相当好榜样确切的问题,使用协程s和LuaSocket的socket.select()函数来防止忙碌。

不幸的是我不相信有什么办法可以在socket.select中使用socket.http函数; PiL示例中的代码通常都是您需要的,但它并不处理一些相当常见的情况,例如请求的URL发送重定向。

+0

我实际上已经根据PiL链接给出了一个好主意。谢谢! – Josh 2012-07-15 21:57:45

5

协程并不像这样工作。事实上,它们是阻塞的。

问题协程解决方案是“我想要一个函数,我可以执行一段时间,然后返回去做其他事情,然后返回并保持与离开时相同的状态”。

请注意,我没有说“我希望它在我做其他事情时继续运行”;代码流在协程上“停止”,并且只在您回到它时继续执行。

使用协程可以修改代码的行为,并使其更加明显或清晰。但它仍然是严格单线程的。

请记住,Lua实现必须由C99指定。由于这个标准没有带有线程实现,所以默认情况下,Lua是严格单线程的。如果你想要多线程,你需要把它挂到外部库。例如,luvit用libuv lib挂钩Luajit来实现此目的。

一对夫妇很好的参考: