Unity 中的 async-await 关键字解析

入门篇参考之前的文章:
Unity 中的 async-await 咋用

首先,理解一下这两个关键字:
1.async:可以把方法标识为异步
2.await:异步方法在碰到await表达式之前都是使用同步的方式执行

await 后面等待什么呢?
C#提供了一个接口规范,就叫做 INotifyCompletion,命名空间是 System.Runtime.CompilerServices
其实现有:TaskAwaiter 以及泛型版本 TaskAwaiter

其实在Unity中使用 async,还是会在当前线程里面执行,怎么做到的呢?

void Start()
{
    Debug.Log(Thread.CurrentThread.ManagedThreadId);//1
    Test();
}

async void Test()
{
    await Task.Delay(TimeSpan.FromSeconds(1f));
    Debug.Log(Thread.CurrentThread.ManagedThreadId);//1
}

在Unity框架下,它的工作原理是因为:
Unity提供了一个名为 UnitySynchronizationContext 的默认 SynchronizationContext
它会自动收集每个帧排队的任何异步代码,并在主要的Unity线程上继续运行它们。

那么 SynchronizationContext 是啥?
SynchronizationContext 代表 线程上下文
主要有两个方法:
1.Send():是简单的在当前线程上去调用委托来实现(同步调用)。也就是在子线程上直接调用线程执行,等线程执行完成后子线程才继续执行。
2.Post():在线程池上去调用委托来实现(异步调用)。这是子线程会从线程池中找一个线程去调线程,子线程不等待UI线程的完成而直接执行自己下面的代码。


实现一个调度器实现原理如下:
主要是通过 SynchronizationContext.Current 进行上下文判断
1.如果是一个,就调用 Send 方法(或者直接调用 action)
2.如果不是一个,就调用 Post 方法

public class SyncContextUtil
{
    //RuntimeInitializeOnLoadMethod 在物体的初始化之前就调用 
    //  流程:BeforeSceneLoad -> Awake -> OnEnable ->AfterSceneLoad -> Start
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    static void Install()
    {
        UnitySynchronizationContext = SynchronizationContext.Current;
        UnityThreadId = Thread.CurrentThread.ManagedThreadId;
    }

    //Unity主线程Id
    public static int UnityThreadId
    {
        get; private set;
    }

    //SynchronizationContext 线程上下文
    //主要有两个方法:
    //  1.Send():是简单的在当前线程上去调用委托来实现(同步调用)。也就是在子线程上直接调用UI线程执行,等UI线程执行完成后子线程才继续执行。
    //  2.Post():在线程池上去调用委托来实现(异步调用)。这是子线程会从线程池中找一个线程去调UI线程,子线程不等待UI线程的完成而直接执行自己下面的代码。
    public static SynchronizationContext UnitySynchronizationContext
    {
        get; private set;
    }

    //实现Unity的多线程调度器
    public static void RunOnUnityScheduler(Action action)
    {
        if (SynchronizationContext.Current == SyncContextUtil.UnitySynchronizationContext)
        {
            //本质上就是直接 action()
            //SyncContextUtil.UnitySynchronizationContext.Send(_ => action(), null);
            action();
        }
        else
        {
            SyncContextUtil.UnitySynchronizationContext.Post(_ => action(), null);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值