UH2S1L10——协同程序

协同程序概念已在Unity基础讲过,这里不再赘述

本章代码关键字

1
2
3
4
5
6
coroutine.create()        --创建协程,返回thread类型变量
coroutine.wrap() --创建协程,返回function类型变量
coroutine.yield() --挂起协程,参数用于返回协程
coroutine.resume() --启动thread类型的协程变量,返回协程运行是否成功和协程返回值
coroutine.status() --检测thread类型的协程变量的运行状态
coroutine.running() --返回当前正在运行的协程的协程号

协程的创建

使用coroutine.create​传入作为协程的函数,创建协程,检查类型发现其变量类型为thread

1
2
3
4
5
6
function Fun()
print(123)
end

local co = coroutine.create(Fun)
print(type(co))
1
thread

使用coroutine.wrap​传入作为协程的函数,也可以创建协程,检查类型发现其变量类型为function
一旦你调用这个返回的函数,就进入coroutine​,和create​功能重复

1
2
3
4
5
6
function Fun()
print(123)
end

local co2 = coroutine.wrap(Fun)
print(type(co2))
1
function

协程的运行

如果使用coroutine.create​创建协程,则需要使用coroutine.resume()​传入协程变量,开启协程

1
2
3
4
5
6
7
8
9
print("**********协同程序************")
function Fun()
print(123)
end

local co = coroutine.create(Fun)
print(type(co))

coroutine.resume(co)
1
2
3
**********协同程序************
thread
123

如果使用coroutine.wrap​创建协程,则直接调用返回的函数,开启协程

1
2
3
4
5
6
7
8
9
print("**********协同程序************")
function Fun()
print(123)
end

local co2 = coroutine.wrap(Fun)
print(type(co2))

co2()
1
2
3
**********协同程序************
function
123

协程的挂起

协程函数内部通过coroutine.yield​函数挂起协程,该函数可以有参数,即挂起后向外部返回什么值
外部在启动协程后会得到两个值,一个是协程是否运行成功,另一个是协程挂起或return​后返回了什么值

协程挂起后需要重新运行协程,协程函数会从上次挂起的地方继续向下执行逻辑,直到再次挂起或执行完毕

通过coroutine.wrap​创建的协程,启动协程时不会返回协程是否运行成功,只会返回挂起或return​返回了什么值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
print("**********协程的挂起************")
function Fun2()
local i = 1
while true do
print(i)
-- 协程的挂起函数
coroutine.yield("协程挂起: " .. i)
i = i + 1
end
end

local co3 = coroutine.create(Fun2)
local isOK, tempI = coroutine.resume(co3)
print(isOK, tempI)
local isOK, tempI = coroutine.resume(co3)
print(isOK, tempI)
local isOK, tempI = coroutine.resume(co3)
print(isOK, tempI)

local co4 = coroutine.wrap(Fun2)
print("返回值: " .. co4())
print("返回值: " .. co4())
print("返回值: " .. co4())
1
2
3
4
5
6
7
8
9
10
11
12
13
**********协程的挂起************
1
true 协程挂起: 1
2
true 协程挂起: 2
3
true 协程挂起: 3
1
返回值: 协程挂起: 1
2
返回值: 协程挂起: 2
3
返回值: 协程挂起: 3

值得一提的是,当协程函数执行完毕(return​了)而非挂起时,再次启动协程会失败,如果接收其返回值会得到启动失败的信息
coroutine.wrap​创建的协程调用执行会直接报错,报错信息也是启动失败的信息)

1
2
3
4
5
6
7
8
print("**********协同程序************")
function Fun()
print(123)
end

local co = coroutine.create(Fun)
coroutine.resume(co)
print(coroutine.resume(co))
1
2
123
false cannot resume dead coroutine
1
2
3
4
5
6
7
8
print("**********协同程序************")
function Fun()
print(123)
end

local co2 = coroutine.wrap(Fun)
co2()
print(co2())
1
2
3
4
5
lua: e:\CodeField\VSC\Lua_Learn\tempCodeRunnerFile.lua:8: cannot resume dead coroutine
stack traceback:
[C]: in function 'co2'
e:\CodeField\VSC\Lua_Learn\tempCodeRunnerFile.lua:8: in main chunk
[C]: ?

协程的状态

协程对象有三种状态:

  • dead 结束
  • suspended 暂停
  • running 运行中

通过coroutine.status​传入要判断的协程,可以得到协程的状态(其中如果要获取running这个状态只能在协程内部获取
(别忘了装载协程使用全局变量,不然检查不到)

coroutine.status主要用于检测create​****创建的协同程序, wrap​****创建的无法通过status进行状态检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
print("**********协程的状态************")
function Fun()
print(123)
end
local co = coroutine.create(Fun)

function Fun2()
local i = 1
while true do
print(i)
i = i + 1
print(coroutine.status(co3))
coroutine.yield("协程挂起: " .. i)
end
end
co3 = coroutine.create(Fun2)

coroutine.resume(co)
coroutine.resume(co3)

print(coroutine.status(co3))
print(coroutine.status(co))
1
2
3
4
5
6
**********协程的状态************
123
1
running
suspended
dead

查看运行中的协程

coroutine.running()​可以获取当前正在执行的协程的协程号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
print("**********协程的状态************")
function Fun()
print(123)
print(coroutine.running())
end
local co = coroutine.create(Fun)

function Fun2()
local i = 1
while true do
print(i)
i = i + 1
print(coroutine.running())
coroutine.yield("协程挂起: " .. i)
end
end
co3 = coroutine.create(Fun2)

coroutine.resume(co)
coroutine.resume(co3)
1
2
3
4
5
**********协程的状态************
123
thread: 004ED7E0
1
thread: 004EE300