Unity异步编程【6】——Unity中的UniTask如何取消指定的任务或所有的任务

news2024/11/24 6:27:13

今天儿童节,犬子已经9个多月了,今天是他的第一个儿童节。中年得子,其乐无穷(音:ku bu kan yan)…回头是岸啊

〇、 示例效果

一连创建5个异步任务[id 从0~4],先停止其中的第id == 4的任务,再停止所有的任务
请添加图片描述

一、CancellationTokenSource有什么用?

在Unity中,CancellationTokenSource用于创建和控制CancellationToken实例,以便在需要时请求取消异步操作。CancellationToken实例是一种轻量级的结构,用于在异步操作执行期间检查是否已请求取消。

首先,您需要创建一个CancellationTokenSource实例,用于创建和控制CancellationToken实例。然后,将CancellationToken实例传递给您要执行的异步任务,以便在需要时请求取消操作。最后,您可以调用CancellationTokenSource实例的Cancel()方法来请求取消所有使用该CancellationToken的异步操作。

二、cts用法示例

  • 1、定义一个异步任务——它的参数为CancellationToken
public async UniTask FlowAsync(CancellationToken ctk)
    {
        foreach (var script in scripts)
        {
            Debug.Log($"执行步骤:{script.name}");
            await (script as IFlowAsync).FlowAsync(ctk);
        }
    }
  • 2、启动一个cts任务,用于管理FlowAsync任务
    生成一个 cts 实例,TaskSingol的定义见下文《用多个CancellationTokenSource实例来管理多个异步任务管理》
#if UNITY_EDITOR
    [ContextMenu("测试步骤")]
#endif
    void testAsync()
    {
        var ctsInfo = TaskSingol.CreatCts(); //生成一个 cts 实例,TaskSingol的定义见下文《用多个CancellationTokenSource实例来管理多个异步任务管理》
        FlowAsync(ctsInfo.cts.Token);        //传入token  
    }

三、用多个CancellationTokenSource实例来管理多个异步任务管理

  • 定义一个全局的class,用于管理不同异步的cancellation操作
  • 每次启动一个异步任务,都对应一个CancellationTokenSource实例和一个task id
  • 包含功能:
    1、创建一个异步任务
    2、取消所有异步任务
    3、取消指定的异步任务
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using System;
using System.Linq;

/// <summary>
/// 任务信号
/// </summary>
public static class TaskSingol
{
    /// <summary>
    /// 任务信息
    /// </summary>
    [Serializable]
    public class CtsInfo
    {
        /// <summary>
        /// 任务id
        /// </summary>
        [SerializeField]
        public int id;

        /// <summary>
        /// cst实例
        /// </summary>
        [SerializeField]
        public CancellationTokenSource cts;
    }

    /// <summary>
    /// 任务池子
    /// </summary>
    public static List<CtsInfo> ctsInfos = new List<CtsInfo>();

    /// <summary>
    /// 任务编号【自增】
    /// </summary>
    private static int id = 0;

    /// <summary>
    /// 创建一个任务
    /// </summary>
    /// <returns></returns>
    public static CtsInfo CreatCts()
    {
        var cts = new CancellationTokenSource();
        var ci = new CtsInfo{cts = cts,id = id};
        id++;
        ctsInfos.Add(ci);
        return ci;
    }

    /// <summary>
    /// 取消所有的任务
    /// </summary>
    public static void CancelAllTask()
    {
        ctsInfos.ForEach(ci=>ci.cts.Cancel());
    }

    /// <summary>
    /// 取消指定的任务
    /// </summary>
    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;

/// <summary>
/// 接口:定义一个叫FlowAsync的异步方法
/// </summary>
public interface IFlowAsync
{
    public UniTask FlowAsync(CancellationToken ctk);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/609275.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flutter进阶篇-布局(Layout)原理

1、约束、尺寸、位置 overrideWidget build(BuildContext context) {return Scaffold(body: LayoutBuilder(builder: (context, constraints) {print("body约束:" constraints.toString());return Container(color: Colors.black,width: 300,height: 300,child: L…

【企业化架构部署】基于Nginx搭建LNMP架构

文章目录 一、安装 MySQL 数据库1. 安装Mysql环境依赖包2. 创建运行用户3. 编译安装4. 修改mysql 配置文件5. 更改mysql安装目录和配置文件的属主属组6. 设置路径环境变量7. 初始化数据库8. 添加mysqld系统服务9. 修改mysql 的登录密码10. 授权远程登录 二、编译安装 nginx 服务…

Maven 工具

Maven 工具 Maven简介Maven 基础概念创建 Maven项目依赖配置生命周期与插件分模块开发聚合和继承聚合继承聚合与继承的区别 属性版本管理多环境配置与应用私服 Maven简介 Maven 本质是一个项目管理工具&#xff0c;将项目开发和管理过程抽象成一个项目对象模型&#xff08;POM…

【爬虫】3.4爬取网站复杂数据

1. Web服务器网站 进一步把前面的Web网站的mysql.html, python.html, java.html丰富其中 的内容&#xff0c;并加上图形&#xff1a; mysql.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>my…

ICV报告: 智能座舱SoC全球市场规模预计2025年突破50亿美元

在智能化、互联化车辆需求不断增加的推动下&#xff0c;汽车行业正在经历一场范式转变。这一转变的前沿之一是智能座舱SoC。本市场研究报告对智能座舱SoC市场进行了全面的分析&#xff0c;包括其应用领域、当前状况和主要行业参与者。 智能座舱SoC指的是现代汽车智能座舱系统的…

Qt6.5.1+WebRTC学习笔记(十)开发环境搭建(win10+vs2022)

一、准备 1.操作系统win10 64位 2.合理的上网方式&#xff0c;需要正常访问google,最好有40G以上流量 3.安装VS2022&#xff0c;笔者使用的是社区版&#xff0c;并选中C相关&#xff0c;笔者设置如下 注意&#xff0c;win10的sdk需要是10.0.22621.0&#xff0c;其他版本可能…

吴恩达 ChatGPT Prompt Engineering for Developers 系列课程笔记--06 Transforming

06 Transforming 大语言模型&#xff08;LLM&#xff09;很擅于将输入转换为不同格式的输出&#xff0c;比如翻译、拼写校正或HTML格式转化。相比于复杂的正则表达式&#xff0c;Chat GPT实现更加准确和高效。 1) 不同语种的转换 下述语句实现了英文到西班牙语的翻译。 pro…

Windows IIS/docker+gunicorn两种方式部署django项目

写在最前 本篇文章并不涉及如何使用宝塔搭建django项目&#xff0c;仅适用于windows和docker部署&#xff0c;其中docker是运行在linux平台上的&#xff0c;如果您想在windows上运行docker&#xff0c;请自行搜索如何在windows上运行docker 一、Windows IIS部署 软件版本Win…

MySQL-Linux版安装

MySQL-Linux版安装 1、准备一台Linux服务器 云服务器或者虚拟机都可以&#xff1b; Linux的版本为 CentOS7&#xff1b; 2、 下载Linux版MySQL安装包 下载地址 3、上传MySQL安装包 使用FinalShell软件上传即可&#xff01; 4、 创建目录,并解压 mkdir mysqltar -xvf my…

【SpringCloud学习笔记】zuul网关

【SpringCloud学习笔记】 为什么需要网关zuul网关搭建zuul网关服务网关过滤器 为什么需要网关 微服务项目一般有多个服务&#xff0c;每个服务的地址都不同&#xff0c;客户端如果直接访问服务&#xff0c;无疑是增加客户端开发难度&#xff0c;项目小还好&#xff0c;如果项目…

【图像任务】Transformer系列.1

介绍几篇改进Transformer模型实现亮度增强、图像重建的任务&#xff1a;LLFormer&#xff08;AAAI2023&#xff09;&#xff0c;DLSN&#xff08;TPAMI2023&#xff09;&#xff0c;CAT&#xff08;NeurIPS2022&#xff09;。 Ultra-High-Definition Low-Light Image Enhanceme…

Linux | 进程控制

啊我摔倒了..有没有人扶我起来学习.... &#x1f471;个人主页&#xff1a; 《 C G o d 的个人主页》 \color{Darkorange}{《CGod的个人主页》} 《CGod的个人主页》交个朋友叭~ &#x1f492;个人社区&#xff1a; 《编程成神技术交流社区》 \color{Darkorange}{《编程成神技术…

Redis的内存策略

过期Key处理: 1)Redis之所以性能强大&#xff0c;最主要的原因就是基于内存来存储&#xff0c;然而单节点的Redis内存不宜设置的过大&#xff0c;否则会影响持久化或者是主从复制的性能&#xff0c;可以通过修改配置文件来设置redis的最大内存&#xff0c;通过maxmemory 1gb&am…

javaScript蓝桥杯-----粒粒皆辛苦

目录 一、介绍二、准备三、目标四、代码五、完成 一、介绍 俗话说“民以食为天”&#xff0c;粮食的收成直接影响着民生问题&#xff0c;通过对农作物产量的统计数据也能分析出诸多实际问题。 接下来就让我们使用 ECharts 图表&#xff0c;完成 X 市近五年来的农作物产量的统…

Python批量下载参考文献|基于Python的Sci-Hub下载脚本|Python批量下载sci-hub文献|如何使用sci-hub批量下载论文

本篇博文将介绍如何通过Python的代码实现快速下载指定DOI号对应的文献&#xff0c;并且使用Sci-Hub作为下载库。 一、库函数准备 在开始之前&#xff0c;我们需要先安装一些必要的库&#xff0c;包括&#xff1a; requests&#xff1a;发送HTTP请求并获取响应的库&#xff1…

南山城市更新--向南村(一期,二期)项目详情

向南村&#xff08;一期&#xff09;城市更新单元项目简介 项目于2010年被列入《深圳城市更新单元规划制定计划第一批计划》中&#xff0c;申报主体为向南实业股份有限公司&#xff0c;后与恒大合作开发。 项目位于南山区桂庙路南侧&#xff0c;毗邻前海、衔接后海&am…

经典算法:Fenwick Tree

经典算法&#xff1a;Fenwick Tree 1. 算法简介2. 原理介绍3. 算法实现4. 例题说明 1. 解题思路2. 代码实现 5. 参考链接 1. 算法简介 Fenwick Tree又称为Binary Indexed Tree&#xff0c;也算是一种常见的数据结构了。 他其实某种意义上来说算是Segment Tree的一种变体&…

克隆虚拟机

上一篇我们已经讲过了启动虚拟机并安装Linux系统&#xff0c;下面我们来讲一下如何通过已经创建好的虚拟机spark01克隆出spark02和spark03来&#xff0c;从而满足搭建大数据集群环境需要多台虚拟机的需求。 首先我们要理解两个概念&#xff1a; 1.完整克隆 完整克隆的虚拟机可…

【算法证明 三】计算顺序统计量的复杂度

计算顺序统计量&#xff0c;在 c 标准库中对应有一个函数&#xff1a;nth_element。其作用是求解一个数组中第 k 大的数字。常见的算法是基于 partition 的分治算法。不难证明这种算法的最坏复杂度是 Θ ( n 2 ) \Theta(n^2) Θ(n2)。但是其期望复杂度是 Θ ( n ) \Theta(n) …

从源码全面解析 dubbo 服务暴露的来龙去脉

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#x1f4d5;系列专栏&#xff1a;Java设计模式、Spring源码系列、Netty源码系列、Kafka源码系列、JUC源码…