如何理解协程

概念

协程(英语:coroutine)是计算机程序的一类组件,推广了协作式多任务的子程序,允许执行被挂起与被恢复。
相对子例程而言,协程更为一般和灵活,但在实践中使用没有子例程那样广泛。
协程更适合于用来实现彼此熟悉的程序组件,如协作式多任务、异常处理、事件循环、迭代器、无限列表和管道。

协程可以通过yield来调用其它协程,接下来的每次协程被调用时,从协程上次yield返回的位置接着执行,通过yield方式转移执行权的协程之间不是调用者与被调用者的关系,而是彼此对称、平等的。

例程/协程

由于协程不如子例程那样被普遍所知,下面对它们作简要比较:

子例程可以调用其他子例程,调用者等待被调用者结束后继续执行,故而子例程的生命期遵循后进先出,即最后一个被调用的子例程最先结束返回。协程的生命期完全由对它们的使用需要来决定。

子例程的起始处是惟一的入口点,每当子例程被调用时,执行都从被调用子例程的起始处开始。协程可以有多个入口点,协程的起始处是第一个入口点,每个yield返回出口点都是再次被调用执行时的入口点。
子例程只在结束时一次性的返回全部结果值。协程可以在yield时不调用其他协程,而是每次返回一部分的结果值,这种协程常称为生成器或迭代器。

现代的指令集架构通常提供对调用栈的指令支持,便于实现可递归调用的子例程。在以Scheme为代表的提供续体的语言环境下,恰好可用此控制状态抽象表示来实现协程。
子例程可以看作是特定状况的协程,任何子例程都可转写为不调用yield的协程。

程序执行过程
2023-11-19T10:33:57.png
执行过程
测试
在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中得到如下结果

2023-11-19T10:33:44.png
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之间执行,起到了分割功能的作用。提高了程序执行效率。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    请登录后查看评论内容