看了好几次协同程序都始终没能搞懂其中resume是如何与yield进行数据交流的,今天终于看懂了,让我们从头说起
基本语法
coroutine.create( )
创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用
重启coroutine,和create配合使用
挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果
查看coroutine的状态
注:coroutine的状态有三种:dead,suspend,running,具体什么时候有这样的状态请参考下面的程序
创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复
返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号
实例讲解
function foo (a)
print("foo 函数输出", a)
return coroutine.yield(2 * a) -- 返回 2*a 的值
end
co = coroutine.create(function (a , b)
print("第一次协同程序执行输出", a, b) -- co-body 1 10
local r = foo(a + 1)
print("第二次协同程序执行输出", r)
local r, s = coroutine.yield(a + b, a - b) -- a,b的值为第一次调用协同程序时传入
print("第三次协同程序执行输出", r, s)
return b, "结束协同程序" -- b的值为第二次调用协同程序时传入
end)
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("--分割线----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("---分割线---")
上面代码的输出如下
第一次协同程序执行输出 1 10
foo 函数输出 2
main true 4
--分割线----
第二次协同程序执行输出 r
main true 11 -9
---分割线---
第三次协同程序执行输出 x y
main true 10 结束协同程序
---分割线---
main false cannot resume dead coroutine
---分割线---
个人分析
第一个分割线之前的内容很好理解,resume调用时,参数传递分两种情况,一种是第一次,把参数传递给协程主程序,之后的resume就把参数传递给yield函数,继续协程函数运行。
首先第一次传递参数给主程序,调用foo 输出2,遇到yield,协程返回状态和yield的参数 main true 4。
然后第二次resume,传递参数是“r”,这时候协程从上次yield的地方开始继续执行,也就是第一个local r的赋值,此时传递参数是字符串“r”,那么yield的参数就是“r”,local r的值就被赋值成了字符串。之后的x,y也同理
最后函数执行结束返回return之后,这时再去调用resume,因为程序已经结束了,所以是dead状态,返回false
这段程序的关键就在于,第一次之后每次resume的参数都作为上次挂起时候yield的返回值,可以在程序内继续赋值,相当于传递参数,而yield本身相当于是暂时性的return语句,yield本身的参数用来做resume函数的返回值,yield(a,b)也就相当于是return a,b
这就是之前很绕的一段话:resume的参数是yield的返回值,yield的参数是resume的返回值。真的太绕了。。。