在学习ET的过程中,我们经常看到ETVoid和ETTask的身影
比如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
public async ETTask LoadBundleAsync(string assetBundleName) { assetBundleName = assetBundleName.ToLower(); string[] dependencies = AssetBundleHelper.GetSortedDependencies(assetBundleName); foreach (string dependency in dependencies) { if (string.IsNullOrEmpty(dependency)) { continue; }
await this.LoadOneBundleAsync(dependency); } }
|
再比如
1 2 3 4 5 6 7 8 9 10 11 12 13
| public async ETVoid TestActor() { try { M2C_TestActorResponse response = (M2C_TestActorResponse)await SessionComponent.Instance.Session.Call( new C2M_TestActorRequest() { Info = "actor rpc request" }); Log.Info(response.Info); } catch (Exception e) { Log.Error(e); } }
|
异同点
我们先不管他们代表什么意思,先找找他们的共同点和不同点
共同点:都有async修饰符
不同点:
ETTask可以有返回值,可等待返回结果,他会等待自身内部任务完成再执行下面的语句,通俗点说可以把异步方法变成同步那样的写法
ETVoid不能有返回值,不可等待返回结果,不做特殊处理,它的状态是不可获得的,他不会等待自身内部任务完成再执行下面的语句
那他们又有什么用呢?
ETTask
具体来说就是你异步加载一个超级大的模型,要花5,6秒钟,而下面的操作是在模型已经加载完成的基础上进行的,
这个时候,一般情况下是要写回调函数的,然而,使用ETTask修饰这个加载模型的函数,调用的时候加上await关键字,就会等到模型加载完成再进行下面的操作,
换句话说,await本身可以看成一个空的回调函数,异步操作处理完了,才会执行await下面的语句
ETVoid
比如你Map服务器从Gate服务器收到创建一个游戏物体的请求,就可以使用ETVoid
再比如你点击一个按钮,所触发的事件函数可以用ETVoid(emmm,貌似ETTask更合理一点?因为你要等他处理完这一次的事件再处理即将到来的事件)
因为你不用关心它的状态
总来说网络层使用ETVoid要比客户端正常的逻辑层频繁的多得多
举个具体的例子
正确做法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public async ETTask Init() { TimerComponent timerComponent = ETModel.Game.Scene.GetComponent<TimerComponent>(); await timerComponent.WaitAsync(5000); await ETModel.Game.Scene.GetComponent<FUIPackageComponent>().AddPackageAsync(FUIPackage.FUILogin); await ETModel.Game.Scene.GetComponent<FUIPackageComponent>().AddPackageAsync(FUIPackage.FUILobby); }
await Init();
Game.EventSystem.Run(EventIdType.ShowLoginUI);
|
错误做法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public async ETVoid Init() { TimerComponent timerComponent = ETModel.Game.Scene.GetComponent<TimerComponent>(); await timerComponent.WaitAsync(5000); await ETModel.Game.Scene.GetComponent<FUIPackageComponent>().AddPackageAsync(FUIPackage.FUILogin); await ETModel.Game.Scene.GetComponent<FUIPackageComponent>().AddPackageAsync(FUIPackage.FUILobby); }
Init().Coroutine();
Game.EventSystem.Run(EventIdType.ShowLoginUI);
|
总结
最后,ETTask是单线程的,没有开新线程
注意,如果在调用async修饰的方法(返回类型为ETTask)时不加await修饰符,这个方法将不会等待自身任务完成,也就是说,不会等待返回结果,几乎(执行到第一个await语句里的返回的ETTask就返回)是立马执行下面的代码了。
最后的最后推荐大家几篇文章
这是一篇讲异步和多线程的文章
这是一篇讲async和await的文章
这是一篇讲async 的三大返回类型的文章
这是一篇讲async/await实现原理的文章
然后是大家最喜欢的熊猫语录时间