unity 主线程调用_Unity实践—多线程任务队列实现

本文介绍了如何在 Unity 中实现多线程任务队列,包括串行与并发队列,同步与异步执行,以及主线程同步。重点探讨了Task、TaskScheduler和Loom在实现过程中的作用,提供了具体的源码实现和使用示例。通过LimitedConcurrencyLevelTaskScheduler控制并发数,Loom实现主线程方法调用。
摘要由CSDN通过智能技术生成

Unity 已可使用 Thread、Task 等处理多线程任务,但缺少成熟的多线程任务队列工具,所以在此实现一个,代码已上传 Git 项目 GRUnityTools,可直接下载源码或通过 UPM 使用

本文原地址:Unity实践—多线程任务队列实现

实现目标

  1. 串行与并发队列

队列是首要实现目标,且需要串行与并发两种队列,以覆盖不同需求

2. 同步与异步执行

因任务队列过多可能阻塞主线程,所以除同步执行外还需要多线程异步操作

3. 主线程同步

因为有多线程,但 Unity 部分操作只能在主线程执行,所以还需要线程同步到主线程

实现方式

  1. Task

Task 为当前 .Net 提供的实用性最高的多线程接口,可实现任务的监控与操纵

2. TaskScheduler

Task 专用调度器,可更便捷地实现 Task 队列调度

3. Loom

Loom 为网络上广为流传的 Unity 中调用主线程的工具类,目前找不到源码最原始地址,代码拷贝自知乎

实现过程

方案选择

最初即决定使用 Task 作为队列基本单位,但完全没有考虑 TaskScheduler。原计划手动实现一个调度器,负责保存传入的 Task 放入队列,可设置同步异步,根据设置实现对队列的不同操作。后来再研究微软官方文档时发现在其 Task 文档的示例中有一个 LimitedConcurrencyLevelTaskScheduler 的演示代码,直接通过 TaskScheduler 实现了可控并发数量的调度器,且当设置并发数为1时队列中的任务会逐一按顺序执行即产生了串行队列效果

TaskScheduler 有两种使用方式

方式一:为 TaskFactory 配置 TaskScheduler,通过 TaksFactory 使用配置的调度器启动 Task

//创建并发数32的调度器
LimitedConcurrencyLevelTaskScheduler scheduler = new LimitedConcurrencyLevelTaskScheduler(32); 
//方式1 
TaskFactory factory = new TaskFactory(scheduler);
factory.StartNew(()=>{
    
  //执行任务
});

方式二:直接使用 Task.Start(TaskFactory) 方法

//创建并发数1的调度器(此时即为串行队列效果)
LimitedConcurrencyLevelTaskScheduler scheduler = new LimitedConcurrencyLevelTaskScheduler(1);
//声明一个 Task 对象
Task task = new Task(()=>{
    
  //任务
});
//启动 Task 指定调度器
task.Start(scheduler);

编写源码

创建名为 TaskQueue 的类,添加变量

//根据需求设置默认并发数
private const int DefaultConcurrentCount = 32;
//线程锁
private static object _lock = new object();
//默认静态串行队列对象
private static TaskQueue _defaultSerial;
//默认静态并发队列对象
private static TaskQueue _defaultConcurrent;
//持有的调度器
private LimitedConcurrencyLevelTaskScheduler _scheduler;  

//提供默认串行队列
public static TaskQueue DefaultSerailQueue
{
    
    get
    {
    
        if (_defaultSerial == null)
        {
    
            lock (_lock)
            {
    
                if (_defaultSerial == null)
                {
    
                    _defaultSerial = new TaskQueue(1);
                }
            }
        }
        return _defaultSerial;
    }
}

//提供默认并发队列
public static TaskQueue DefaultConcurrentQueue
{
    
    get
    {
    
        if (_defaultConcurrent == null)
        {
    
            lock (_lock)
            {
    
                if (_defaultConcurrent == null)
                {
    
                    _defaultConcurrent = new TaskQueue(DefaultConcurrentCount);
                }
            }
        }
        return _defaultConcurrent;
    }
}

提供快捷构造方法

//默认构造方法,因 Loom 为 UnityEngine.Monobehaviour对象,所以必须执行初始化方法将其加入场景中
public TaskQueue(int concurrentCount)
{
    
    _schedu
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值