前言
Lua協同程式: 開啟另一個邏輯處理和c#一樣,同一時間隻能有一個協同程式被執行
線程:同一時間,可以有多個線程執行
程序:線程的一個載體,一個程式的運作獨立為一個程序,程序和程序之間都有自己獨立的儲存單元、一個程序可以包含多個線程、多個線程之間共享存儲單元。
比如打開一個手機遊戲,這個遊戲就有一個程序,遊戲内部有很多線程同時運作,線程都有一個共享單元來擷取存儲資料
Lua中協同程式的所有函數都被放進一個叫coroutine的表(table)中
Lua中協同程式的4種狀态: 運作、挂起、死亡、正常
一、coroutine.create 建立協同程式
建立協同程式,create函數參數位數一個函數
該參數就是協同程式的工作函數,參數函數一般為匿名函數
create函數有一個傳回值->協同程式
local c1 = coroutine.create(function()
print("我是協同程式")
end)
二、coroutine.status檢視狀态
協同程式建立後預設為suspended挂起狀态,協同程式執行完變成dead死亡狀态
local c1 = coroutine.create(function()
print("我是協同程式")
end)
print(coroutine.status(c1)) --suspended 挂起
三、coroutine.resume 執行協同程式(開始協同程式)
local c1 = coroutine.create(function()
print("我是協同程式")
end)
print(coroutine.status(c1)) --suspended 挂起
coroutine.resume(c1) --執行協同程式(開始協同程式)
print(coroutine.status(c1)) -- dead 死亡結束
四、yield() 挂起
yield 和 c#差不多,停止協同程式,條件滿足繼續向下執行
local c2 = coroutine.create(function()
for i = , do
print(i)
coroutine.yield() -- 挂起,等待喚醒
print("go on") -- 被挂起 go on 不再執行
end
end)
coroutine.resume(c2)
print("LS") -- 挂起後調用
print(coroutine.status(c2)) -- 挂起狀态
coroutine.resume(c2) --喚醒協程繼續向下執行,又被挂起了
print(coroutine.status(c2)) -- 挂起狀态
coroutine.resume(c2) --再次喚醒直接結束了(循環完了2次)
print(coroutine.status(c2)) -- dead結束狀态
五、resume: 方法有兩個傳回值
1.協同程式是否正确執行(正确true,錯誤false)
2. 錯誤原因(正确傳回nill, 錯誤傳回string)
local c3 = coroutine.create(function()
print("協同程式")
error("協同程式發生錯誤")--強制報錯,報錯原因是:協同程式發生錯誤
end
)
local result ,err = coroutine.resume(c3)
print(result)
print(err) -- 協同程式不會報錯,而是在這裡把錯誤原因列印出來
六、resume: 協同程式函數帶有參數
local c4 = coroutine.create(function(name,age)
print(name)
print(age)
end
)
coroutine.resume(c4,"Young",) -- 在調用協同程式後面按順序依次添加
七、resume: 函數第二個傳回值
如果協同程式發生錯誤,第二個傳回值為錯誤資訊
如果協同程式沒有發生錯誤,那麼
第二個傳回值為yield函數的參數
local c5 = coroutine.create(function()
print("lua")
--error("抛出異常") --測試錯誤情況
coroutine.yield("挂起協同程式") --此處不會列印
end)
local result, err = coroutine.resume(c5)
print(result)
print(err) -- 列印傳回yield的參數:挂起協同程式
八、yield函數傳回值就是rusume函數的第二個參數
上面的例子可以說是:yield 函數的參數是resume函數的第二個傳回值
而現在這個例子說的是:yield 函數的傳回值是resume函數的第二個參數
有點複雜,可以根據例子來了解
local c6 = coroutine.create(function(name)
local b = coroutine.yield("傳回給rusume函數")
print(b)--列印A
end)
coroutine.resume(c6,"Y") --第一次"Y"是給協同程式的形參name作實參傳入,但是協同程式被yield挂起了
coroutine.resume(c6,"A") --第二次繼續執行協同程式,此時第二個參數”A“就是yiled函數的傳回值
九、協同程式中函數帶有傳回值
協同程式中函數的第一個傳回值給了resume函數的第二個傳回值上
下次繼續執行協同程式,resume函數傳回值依次為
true
nil
abc
hello lua
local c7 = coroutine.create(function()
coroutine.yield("挂起協同程式")
return nil, "abc", "hello lua"
end)
local result ,err = coroutine.resume(c7)
print(result) -- true
print(err) -- 挂起協同程式
local result , err, ret1, ret2 = coroutine.resume(c7)
print(result) -- true
print(err) -- nil
print(ret1) --abc
print(ret2) --hello lua
官方文檔案例
再讀讀官方文檔的例子,加深了解
yield 函數的參數是resume函數的第二個傳回值,(第一個傳回值是true)
resume函數的第二個參數是yield 函數的傳回值,(第一個參數是協同程式變量(函數)名)
function foo (a)
print("foo", a)
return coroutine.yield(*a)
end
co = coroutine.create(function (a,b)
print("co-body", a, b)
local r = foo(a+)
print("co-body", r)
local r, s = coroutine.yield(a+b, a-b)
print("co-body", r, s)
return b, "end"
end)
print("main", coroutine.resume(co, , ))
print("main", coroutine.resume(co, "r"))
print("main", coroutine.resume(co, "x", "y"))
print("main", coroutine.resume(co, "x", "y"))
列印結果:
When you run it, it produces the following output:
co-body 1 10
foo 2
main true 4
co-body r
main true 11 -9
co-body x y
main true 10 end
main false cannot resume dead coroutine