2012-07-24 53 views
2

我想弄清楚如何使用協程(在Lua中)處理事件。我看到一種常見的做法似乎是創建包裝函數,它產生當前的協同程序,然後在等待的東西出現時恢復它。這似乎是一個很好的解決方案,但這些問題呢? :什麼是使用協程進行事件處理的正確方法?

  1. 你如何等待多個事件在同一時間,分支取決於哪一個先來?還是應該重新設計程序以避免這種情況?

  2. 如何取消一段時間後的等待?事件循環可以在其套接字發送/接收包裝中有超時參數,但是自定義事件呢?

  3. 如何觸發協程從外部改變其狀態?例如,我想要一個被調用的函數,會導致協程跳轉到不同的步驟,或者開始等待不同的事件。

編輯:

目前我有,我註冊一個協程與事件的系統和協程獲取與每次事件發生時的事件名稱和信息作爲參數恢復。在這個系統中,1和2不是問題,3可以通過使coro期望一個特殊的事件名稱來使其跳轉到不同的步驟,並以該名稱作爲arg來恢復。自定義對象也可以有方法以相同的方式註冊事件處理程序。

我只是想知道這是否被認爲是使用協程進行事件處理的正確方法。例如,如果我有讀取事件和計時器事件(作爲讀取超時),並且首先發生讀取事件,則必須手動取消計時器。它似乎不適合順序特性或與協程一起處理事件。

+0

「我只是想知道這是否被認爲是使用協程進行事件處理的正確方法。」如果它適合你,那麼這是正確的方式。爲什麼你會使用一個計時器事件來暫停另一個事件?簡單地在您的事件系統中內置超時是否更有意義? – 2012-07-24 18:57:24

+0

「如果它對你有用,那麼它是正確的方式」它工作正常(但不是很好),我認爲可能有更好的方法,但我錯過了它,因爲我不是非常與協程的家族。 「你爲什麼要使用計時器事件來暫停另一個事件?」。我可以,但自定義事件源將都必須實現超時。也許我可以通過添加一個系統來使用主事件循環註冊自定義事件源來解決這個問題?最後,也許我應該讓處理程序在第一次觸發時自動刪除? – mtk358 2012-07-24 19:22:34

回答

4

你如何等待多個事件在同一時間,分支取決於哪一個先來?

如果您需要爲此使用協程,而不僅僅是您註冊的一個Lua函數(例如,如果您有一個函數做東西,等待一個事件,然後做更多的東西),那麼這個非常簡單。當協程恢復時,coroutine.yield將返回傳遞給coroutine.resume的所有值。

所以只需傳遞事件,並讓腳本自行決定是否它正在等待或不在。事實上,你可以建立一個簡單的函數來做到這一點:

function WaitForEvents(...) 
    local events = {...} 
    assert(#... ~= 0, "You must pass at least one parameter") 

    do 
    RegisterForAnyEvent(coroutine.running()) --Registers the coroutine with the system, so that it will be resumed when an event is fired. 
    local event = coroutine.yield() 
    for i, testEvt in ipairs(events) do 
     if(event == testEvt) then 
     return 
     end 
    end 
    until(false) 
end 

此功能將繼續產生,直到它被賦予已經被解僱的事件之一。循環假定RegisterForAnyEvent是臨時的,只爲一個事件註冊函數,所以每次事件觸發時都需要重新註冊。

如何取消一段時間後的等待?

在上述循環中放置一個計數器,並在一段時間後離開。我將把它作爲讀者的練習。這完全取決於你的應用程序如何測量時間。

如何觸發協程從外部改變其狀態?

你不能將一個Lua函數變成一個不同的「狀態」。你只能調用函數並讓它們返回結果。所以如果你想在某個過程中跳過,你必須編寫你的Lua函數系統以便能夠被跳過。

你如何做到這一點取決於你。你可以讓每一組非等待命令成爲一個獨立的Lua函數。或者你可以設計你的等待狀態,以便能夠跳過。管他呢。

+0

這就是我現在這樣做的方式,但是我發現大多數示例(和庫,例如Copas)使用yielding包裝來阻塞函數,而不是事件註冊函數,然後手動調用yield。我的問題是,我怎樣才能解決我在協程事件系統中遇到的問題,因爲據我所知,它看起來更加優雅,並且是「正確」的方式(如果不是,請糾正我)。 – mtk358 2012-07-24 12:08:06

+0

@ mtk358:然後你把這段代碼放在包裝中。這不是火箭科學。如果你有一些事情要等待多個事件,那麼無論「產生包裝器」都應該讓代碼等待多個事件。 – 2012-07-24 18:59:15

+0

我知道「屈服包裝」一次只能等待一個事件,但我問過這種情況應該避免並寫成不同的方式(但是怎麼做?)。讓我對此產生疑惑的主要原因是Copas使用「讓步包裝」,並且似乎完全忽視了我的三個問題。但它仍然必須以某種方式可用,對吧? – mtk358 2012-07-24 19:26:25

相關問題