Unity多线程管理

作者: Aodota | 来源:发表于2016-12-12 17:11 被阅读649次

    Unity多线程管理

    游戏中我们有许多地方还是有需求要开启多线程,例如下载文件,解压文件等操作,我们需要在Unity下使用
    多线程,那我们如何能更方便的管理多线程呢?

    目前主要需要解决一下几个问题:

    1. 统一开启子线程,防止多线程滥用
    2. 子线程中如何回调主线程

    我目前的解决方案

    • 所有需要异步处理的任务,都继承AsyncTask
    • AsyncTask封装了执行过程,方便对任务的控制。
    • 所有需要回调主线程的地方,统一添加Action。由主线程逐帧调用

    代码如下:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Threading;
    using UnityEngine;
    using LuaFramework;
    
    /// <summary>
    /// 异步任务,交给子线程执行
    /// </summary>
    public abstract class AsyncTask
    {
        // multiThreadMgr
        protected MultiThreadManager MultiThreadMgr {
            get {
                return AppFacade.Instance.GetManager<MultiThreadManager> (ManagerName.MultiThread);
            }
        } 
    
        /// <summary>
        /// 执行任务
        /// </summary>
        public void Execute() {
            try {
                Run();
            } finally {
                MultiThreadMgr.FinishTask (this);
            }
        }
    
        /// <summary>
        /// 关闭执行
        /// </summary>
        public abstract void Close ();
    
        /// <summary>
        /// 开始运行
        /// </summary>
        public abstract void Run ();
    }
    
    /// <summary>
    /// 多线程管理器
    /// </summary>
    public class MultiThreadManager : Manager
    {
        // 需要在主线程执行的操作
        static List<Action> actions = new List<Action> ();
        static List<Action> runningActions = new List<Action> ();
        static object obj = new object();
    
        // 异步任务队列
        static List<AsyncTask> taskList = new List<AsyncTask> ();
    
        /// <summary>
        /// 在主线程中执行
        /// </summary>
        /// <param name="action">Action.</param>
        public void RunOnMainThread (Action action)
        {
            lock (obj) {
                actions.Add (action);
            }
        }
    
        /// <summary>
        /// 添加异步任务
        /// </summary>
        /// <param name="runnable">Runnable.</param>
        public void AddAsyncTask (AsyncTask runnable)
        {
            Debug.Log("AddTask:" + runnable.ToString());
            taskList.Add (runnable);
            Thread thread = new Thread (runnable.Execute);
            thread.IsBackground = true;
            thread.Start ();
        }
    
        /// <summary>
        /// 完成异步任务
        /// </summary>
        /// <param name="runnable">Runnable.</param>
        public void FinishTask (AsyncTask runnable)
        {
            taskList.Remove (runnable);
            Debug.Log ("RemoveTask:" + runnable.ToString () + "," + taskList.Count);
        }
    
        /// <summary>
        /// 主线程更新
        /// </summary>
        void Update ()
        {
            lock (obj) {
                runningActions.Clear ();
                runningActions.AddRange (actions);
                actions.Clear ();
            }
    
            // 处理主线程事件
            if (runningActions.Count > 0) {
                foreach(Action action in runningActions) {
                    action ();
                }
            }
            runningActions.Clear ();
        }
    
        void OnDestroy() {
            for (int i = 0; i < taskList.Count; i++) {
                taskList [i].Close ();
            }
        }
    }
    

    相关文章

      网友评论

      • f888e56a9480:FinishTask会不会有线程安全问题
        Aodota:是有可能的,最好加把锁:smile:

      本文标题:Unity多线程管理

      本文链接:https://www.haomeiwen.com/subject/npnmmttx.html