2012-07-15 47 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來實現此目的。

一對夫婦很好的參考: