概念
协程(英语:coroutine)是计算机程序的一类组件,推广了协作式多任务的子程序,允许执行被挂起与被恢复。
相对子例程而言,协程更为一般和灵活,但在实践中使用没有子例程那样广泛。
协程更适合于用来实现彼此熟悉的程序组件,如协作式多任务、异常处理、事件循环、迭代器、无限列表和管道。
协程可以通过yield来调用其它协程,接下来的每次协程被调用时,从协程上次yield返回的位置接着执行,通过yield方式转移执行权的协程之间不是调用者与被调用者的关系,而是彼此对称、平等的。
例程/协程
由于协程不如子例程那样被普遍所知,下面对它们作简要比较:
子例程可以调用其他子例程,调用者等待被调用者结束后继续执行,故而子例程的生命期遵循后进先出,即最后一个被调用的子例程最先结束返回。协程的生命期完全由对它们的使用需要来决定。
子例程的起始处是惟一的入口点,每当子例程被调用时,执行都从被调用子例程的起始处开始。协程可以有多个入口点,协程的起始处是第一个入口点,每个yield返回出口点都是再次被调用执行时的入口点。
子例程只在结束时一次性的返回全部结果值。协程可以在yield时不调用其他协程,而是每次返回一部分的结果值,这种协程常称为生成器或迭代器。
现代的指令集架构通常提供对调用栈的指令支持,便于实现可递归调用的子例程。在以Scheme为代表的提供续体的语言环境下,恰好可用此控制状态抽象表示来实现协程。
子例程可以看作是特定状况的协程,任何子例程都可转写为不调用yield的协程。
程序执行过程
执行过程
测试
在Unity3D中新建脚本,并将其挂载到相机上,代码内容如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CorutineTest : MonoBehaviour {
private IEnumerator coroutine;
void Start()
{
print("Start " + Time.time + " Seconds");
coroutine = WaitAndPrint();
StartCoroutine(coroutine);
print("协程开启!");
}
private void Update()
{
print("Update " + Time.time + " Seconds");
}
private void LateUpdate()
{
print("LateUpdate " + Time.time + " Seconds");
}
private IEnumerator WaitAndPrint()
{
print("尚未挂起");
yield return null;
print("Coroutine ended : " + Time.time + " Seconds");
}
}
在Console中得到如下结果
console输出结果
分析
- 首先在第一帧执行start函数,这时候完成了Start 0 Seconds。
- 接下来完成了协程函数的开启,跳转到WaitAndPrint函数中,输出print(“尚未挂起”);
- 此时到了yield return null ;但是这里的yield返回值表示在下一帧才开始运行下面的内容。
- 接下来start函数中的前三句都运行完成,开始print(“协程开启!”);,所以在console中得到协程开启的输出语句。
- Start函数运行结束,开始执行Update函数,console得到结果Update 0 Seconds;
- Update函数运行结束,开始执行LateUpdate函数,Console得到结果LateUpdate 0 Seconds ;
- 第一帧结束,开启下一帧,由于协程尚未开启,且Update每一帧执行,所以下一帧以Update开始,Console得到Update 0.02 Seconds;
- 由于yield返回的原因,在这一帧执行协程函数,所以Console得到Coroutine ended : 0.02 Seconds;
- 紧接着执行LateUpdate函数,Console得到LateUpdate 0.02 Seconds;
由以上结果我们可以知道,Coroutine在Update以及LateUpdate之间执行,起到了分割功能的作用。提高了程序执行效率。
请登录后查看评论内容