协程与进程、Unity协程

协程与进程的关系

线程是进程的执行体,拥有一个执行入口,以及从进程虚拟地址空间分配的栈信息,包括用户栈和内核栈
线程可以自己创建多个 名为协程执行体,给他们各自指定执行入口,申请一些内存分配给他们做执行栈,那么线程就可以按需调度这几个执行体了。
为了实现这几个执行体的切换,线程也需要记录执行体的信息,包括但不仅包括:ID、栈的位置、执行入口地址、执行现场

一、用户程序不能操作内核空间,所以只能给协程分配用户栈,二、操作系统对协程一无所知,所以协程又被称为“用户态进程”

协程恢复执行时会根据之前保留的执行现场恢复到中断前的状态,继续执行,这样就通过协程实现了即轻量又灵活的由用户态调度的多任务模型

Unity协程

生命周期
生命周期
生命周期

yield return

要实现IEnumerator接口,需要写一堆繁琐的代码,而yield return则简化了这个过程当在IEnumerator函数中写yield return时,每使用一次yield return则会往迭代器中增加一个元素内容

分帧执行的实现

在对迭代器 MoveNext时,会执行获取到的节点元素的yield return之前,上一个节点元素yield return之后的代码块,于是分帧只需要在每一帧进行yield return即可

IEnumerator e = null;
void Start()
{
    e = TestCoroutine();
}


void LateUpdate()
{
    if (e != null)
    {
        if (!e.MoveNext())
        {
            e = null;
        }
    }
}

IEnumerator TestCoroutine()
{
    Log("Test 1");
    yield return null;              //返回内容为null
    Log("Test 2");
    yield return 1;                 //返回内容为1
    Log("Test 3");
    yield return "sss";             //返回内容为"sss"
    Log("Test 4");
    yield break;                    //跳出,类似普通函数中的return语句
    Log("Test 5");
    yield return 999;               //由于break语句,该内容无法返回
}

void Log(object msg)
{
    Debug.LogFormat("<color=yellow>[{0}]</color>{1}", Time.frameCount, msg.ToString());
}

延迟一定时间执行

yield return的值可以通过moveNext获取到。则可以通过yield return返回一个需要等待的类型,在外面接收到需要等待的类型时,则进行计时,计时一定时间后继续MoveNext即可

private void OnGUI()
{
    if (GUILayout.Button("Test"))       //注意:这里是点击触发,没有放在start里,为什么?
    {
        enumerator = TestCoroutine();
    }
}

void LateUpdate()
{
    if (enumerator != null)
    {
        bool isNoNeedWait = true, isMoveOver = true;
        var current = enumerator.Current;
        if (current is MyWaitForSeconds)
        {
            MyWaitForSeconds waitable = current as MyWaitForSeconds;
            isNoNeedWait = waitable.IsOver(Time.deltaTime);
        }
        if (isNoNeedWait)
        {
            isMoveOver = enumerator.MoveNext();
        }
        if (!isMoveOver)
        {
            enumerator = null;
        }
    }
}

IEnumerator TestCoroutine()
{
    Log("Test 1");
    yield return null;              //返回内容为null
    Log("Test 2");
    yield return 1;                 //返回内容为1
    Log("Test 3");
    yield return new MyWaitForSeconds(2f);  //等待两秒           
    Log("Test 4");
}

StartCoroutine(Method())在哪写的 就会在哪第一次执行Method方法。即如果写在Start中,就会在第一帧执行前执行Method。但如果希望不在第一帧前执行第一次,可以在Method先yield return null

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值