今天儿童节,犬子已经9个多月了,今天是他的第一个儿童节。中年得子,其乐无穷(音:ku bu kan yan)…回头是岸啊
〇、 示例效果
一连创建5个异步任务[id 从0~4],先停止其中的第id == 4的任务,再停止所有的任务
一、CancellationTokenSource有什么用?
在Unity中,CancellationTokenSource用于创建和控制CancellationToken实例,以便在需要时请求取消异步操作。CancellationToken实例是一种轻量级的结构unity没有离线登录选项unity没有离线登录选项,用于在异步操作执行期间检查是否已请求取消。
首先,您需要创建一个CancellationTokenSource实例氛围,用于创建和控制CancellationToken实例。然后,将CancellationToken实例传递给您要执行的异步任务,以便在需要时请求取消操作。最后材质材料,您可以调用CancellationTokenSource实例的Cancel()方法来请求取消所有使用该CancellationToken的异步操作。
二、cts用法示例
public async UniTask FlowAsync(CancellationToken ctk)
{
foreach (var script in scripts)
{
Debug.Log($"执行步骤:{script.name}");
await (script as IFlowAsync).FlowAsync(ctk);
}
}
#if UNITY_EDITOR
[ContextMenu("测试步骤")]
#endif
void testAsync()
{
var ctsInfo = TaskSingol.CreatCts(); //生成一个 cts 实例,TaskSingol的定义见下文《用多个CancellationTokenSource实例来管理多个异步任务管理》
FlowAsync(ctsInfo.cts.Token); //传入token
}
三、用多个CancellationTokenSource实例来管理多个异步任务管理
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System;
using System.Linq;
///
/// 任务信号
///
public static class TaskSingol
{
///
/// 任务信息
///
[Serializable]
public class CtsInfo
{
///
/// 任务id
///
[SerializeField]
public int id;
///
/// cst实例
///
[SerializeField]
public CancellationTokenSource cts;
}
///
/// 任务池子
///
public static List<CtsInfo> ctsInfos = new List<CtsInfo>();
///
/// 任务编号【自增】
///
private static int id = 0;
///
/// 创建一个任务
///
///
public static CtsInfo CreatCts()
{
var cts = new CancellationTokenSource();
var ci = new CtsInfo{cts = cts,id = id};
id++;
ctsInfos.Add(ci);
return ci;
}
///
/// 取消所有的任务
///
public static void CancelAllTask()
{
ctsInfos.ForEach(ci=>ci.cts.Cancel());
}
///
/// 取消指定的任务
///
public static void CancelTask(int id)
{
ctsInfos.Where(ci=>ci.id == id).ToList().ForEach(ci => ci.cts.Cancel());
}
}
四、凡是异步方法都传入cancellationToken,凡是await的地方,都设置cancellationToken 1、 任务A的monobehaviour脚本
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using Cysharp.Threading.Tasks;
public class FlowA : MonoBehaviour, IFlowAsync
{
public async UniTask FlowAsync(CancellationToken ctk)
{
Debug.Log($"我是monobehaviourA {Time.realtimeSinceStartup}");
await UniTask.Delay(2000,cancellationToken:ctk);
Debug.Log($"UniTask.Delay(2000) {Time.realtimeSinceStartup}");
}
}
2、 任务B的monobehaviour脚本
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using Cysharp.Threading.Tasks;
public class FlowB : MonoBehaviour, IFlowAsync
{
public async UniTask FlowAsync(CancellationToken ctk)
{
Debug.Log($"我是monobehaviourB {Time.realtimeSinceStartup}");
await UniTask.Delay(2000,cancellationToken:ctk);
Debug.Log($"UniTask.Delay(2000) {Time.realtimeSinceStartup}");
}
}
3、测试脚本
测试内容:
启动一个任务
停止所有任务
停止指定任务【4】
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
public class TestTask : MonoBehaviour
{
private int idx;
#if UNITY_EDITOR
[ContextMenu("启动一个任务")]
#endif
void test()
{
var ctsInfo = TaskSingol.CreatCts();
RunTask(ctsInfo.id, ctsInfo.cts.Token);
}
#if UNITY_EDITOR
[ContextMenu("停止所有任务")]
#endif
void test2()
{
TaskSingol.CancelAllTask();
Debug.Log("停止所有的任务");
}
#if UNITY_EDITOR
[ContextMenu("停止所有任务【4】")]
#endif
void test3()
{
TaskSingol.CancelTask(4);
Debug.Log("停止任务4");
}
public async UniTask RunTask(int taskIndex,CancellationToken ctk)
{
Debug.Log($"{taskIndex}:任务运行中,1/4等待五秒");
await UniTask.Delay(TimeSpan.FromSeconds(5),cancellationToken:ctk);
Debug.Log($"{taskIndex}:任务运行中,2/4等待五秒");
await UniTask.Delay(TimeSpan.FromSeconds(5), cancellationToken: ctk);
Debug.Log($"{taskIndex}:任务运行中,3/4等待五秒结束,再等5秒");
await UniTask.Delay(TimeSpan.FromSeconds(5), cancellationToken: ctk);
Debug.Log($"{taskIndex}:任务运行中,4/4等待五秒结束,再等20秒");
await UniTask.Delay(TimeSpan.FromSeconds(20), cancellationToken: ctk);
}
}
4、如何让所有的脚本都实现一个FlowAsync的方法——实现一个接口
如下所示,FlowA脚本继承了MonoBehaviour类,还实现了IFlowAsync的接口
下面是FlowA 的脚本关键代码,那么如何定义一个接口Class呢,见下 5
public class FlowA : MonoBehaviour, IFlowAsync
{
public async UniTask FlowAsync(CancellationToken ctk)
{
Debug.Log($"我是monobehaviourA {Time.realtimeSinceStartup}");
await UniTask.Delay(2000,cancellationToken:ctk);
Debug.Log($"UniTask.Delay(2000) {Time.realtimeSinceStartup}");
}
}
5、如何让所有的脚本都实现一个FlowAsync的方法——定义一个接口
using System.Threading;
using Cysharp.Threading.Tasks;
///
/// 接口:定义一个叫FlowAsync的异步方法
///
public interface IFlowAsync
{
public UniTask FlowAsync(CancellationToken ctk);
}
文章来源:https://blog.csdn.net/dzj2021/article/details/130990440