ET–异步协程使用–TimerComponent篇

之前可能也有群友写过一些关于ET框架中TimerComponent的使用教程,我这里写下关于TimerComponent的常规使用跟一些不常规使用的方法以及一些情况下需要使用到的不同的函数。

先来看看TimerComponent中都有哪几个方法,

常规的写法,先来个常规计时器,例子放在登录UI中示例,代码如下,此时能发现运行后,登录按钮开始一秒一秒计时,当我们点击登录按钮,此刻服务端返回消息要切换到大厅界面,登录界面销毁,此刻中的协程仍在TimerComponent中缓存,因为等待时间未到的缘故,于是当在时间到了之后,协程里头的执行的给Text赋值,Text已经不存在,此时会报空引用错误。也就是协程没有绑定UI的生命周期。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 定义
private TimerComponent timer = ETModel.Game.Scene.GetComponent();
 
// 计时器方法, 本方法放在UILoginComponent中作为示例
private async void Counter()
{
    int count = 0;
    while (true)
    {
        await this.timer.WaitAsync(1000);
        loginBtn.GetComponentInChildren().text = $"登录{count}s";
                count++;
    }
}

此刻我们该怎么解决协程生命周期绑定UI周期这个东东呢? Unity官方的协程Coroutine是绑定MonoBehavior周期的,ET中不适用Mono的情况下,TimerComponent提供了一个CancellationToken方案,可以用于绑定生命周期。下面依旧是定期器为例子,做些修改,调用的方法由WaitAsync(long time)变成WaitAsync(long time, CancellationToken cancellationToken),调用的时候传入一个取消标志,销毁UI的时候调用Cancel就可以把当前不想处理的UI相关的协程从Task池中移除出来。WaitAsync中有个CancellationToken的标志,TimerComponent中注册了Cancel的执行方法,当执行Cancel的时候,TimerComponent中将不会存在关于此CancellationToken的协程

1
2
3
4
5
6
7
8
9
public Task WaitAsync(long time, CancellationToken cancellationToken)
{
	TaskCompletionSource tcs = new TaskCompletionSource();
	Timer timer = new Timer { Id = IdGenerater.GenerateId(), Time = TimeHelper.Now() + time, tcs = tcs };
	this.timers[timer.Id] = timer;
	this.timeId.Add(timer.Time, timer.Id);
	cancellationToken.Register(() => { this.Remove(timer.Id); });
	return tcs.Task;
}

具体区别的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// define
private TimerComponent timer = ETModel.Game.Scene.GetComponent();
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken cancelLogin;
 
// 初始化
public void Awake()
{
    ReferenceCollector rc = this.GetParent().GameObject.GetComponent();
    loginBtn = rc.Get("LoginBtn");
    loginBtn.GetComponent().onClick.Add(OnLogin);
    this.account = rc.Get("Account");
    this.cancelLogin = (CancellationToken)this.tokenSource.Token;
    Counter();
}
 
// 定时器方法调用的区别
private async void Counter()
{
    int count = 0;
    while (true)
    {
        await this.timer.WaitAsync(1000, this.cancelLogin);
        loginBtn.GetComponentInChildren().text = $"登录{count}s";
                count++;
    }
}
 
// 从登陆界面跳转大厅界面 的时候,先执行Cancel的方法,将登陆界面的协程从TimerComponent中移除掉,这样就不会抱空引用错误了
private void OnLogin()
{
    this.tokenSource.Cancel();
    Game.Scene.GetComponent().Create(UIType.UILobby);
    Game.Scene.GetComponent().Remove(UIType.UILogin);
}

 

posted on   &大飞  阅读(1339)  评论(0编辑  收藏  举报

编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示