






















而是「凡是可能长时间存在、或受生命周期控制的任务」才应该加 CTS。
Forget() 与 CTS 的核心区别| 对比项 | .Forget() |
CancellationTokenSource |
|---|---|---|
最佳做法是:
👉「任务逻辑用
CTS控制生命周期」,
👉「调用者决定是否await或.Forget()」。
private CancellationTokenSource cts;
private void Start()
{
cts = new();
LoadSceneAsync(cts.Token).Forget(); // 调用方选择忽略
}
private async UniTask LoadSceneAsync(CancellationToken token)
{
await UniTask.Delay(5000, cancellationToken: token);
Debug.Log("场景加载完成");
}
private void OnDestroy()
{
cts.Cancel(); // 防止场景切换或对象销毁时任务泄漏
}
💡 解释:
LoadSceneAsync 不关心是否被 await;
cts.Token 决定任务是否继续;
Forget() 让调用方不阻塞,但内部仍受控。
| 场景 | 是否建议加 CTS | 原因 |
|---|---|---|
private async void Start()
{
await UniTask.Delay(5000);
Debug.Log("对象早就销毁了,但我还在执行!");
}
private async void Start()
{
var token = this.GetCancellationTokenOnDestroy();
await UniTask.Delay(5000, cancellationToken: token);
Debug.Log("对象没销毁才会执行到这里");
}
💡 说明:
GetCancellationTokenOnDestroy()是 UniTask 为 MonoBehaviour 提供的神器,它会在对象销毁时自动取消。
SomeAsync().Forget(); // 我知道它会跑完,不需要返回结果
await SomeAsync().Forget(); // 无意义,Forget返回void
.Forget() 默认吞异常,你可以这样防御:
SomeAsync().Forget(e => Debug.LogException(e));
| 任务类型 | 是否加 CTS | 是否 Forget |
|---|---|---|
你可以用一个父级 Token 控制多个异步任务:
var cts = new CancellationTokenSource();
DoA(cts.Token).Forget();
DoB(cts.Token).Forget();
DoC(cts.Token).Forget();
// 一键取消所有
cts.Cancel();
或者组合多个 Token:
var linked = CancellationTokenSource.CreateLinkedTokenSource(token1, token2);
await UniTask.Delay(1000, cancellationToken: linked.Token);
创建一个 CTS 的开销 ≈ 40~60B GC Alloc;
所以:
👉 建议在 MonoBehaviour 级别缓存,
👉 而不是每次 async 方法都 new 一个。
private CancellationTokenSource cts;
private void Awake() => cts = new();
private void OnDestroy() => cts.Cancel();
public class Example : MonoBehaviour
{
private CancellationTokenSource _cts;
private void Awake()
{
_cts = new();
}
private void OnDestroy()
{
_cts.Cancel();
_cts.Dispose();
}
private void Start()
{
RunAsync(_cts.Token).Forget();
}
private async UniTask RunAsync(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
await UniTask.Delay(1000, cancellationToken: token);
Debug.Log("持续工作中...");
}
}
}
Forget 是“不管结局”,CTS 是“能中断结局”。
只要任务可能「超时、循环、依赖对象存在」,就加 CTS
调用方只关心“我是否等待结果”,就用 Forget
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。